Skip to content

feat(firestore): add DML stages, literals source, and atomic execution option to Node SDK pipelines - #9118

Open
wu-hui wants to merge 19 commits into
mainfrom
feat-node-dml
Open

wu-hui wants to merge 19 commits into
mainfrom
feat-node-dml

Conversation

@wu-hui

@wu-hui wu-hui commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Adds full support for DML stages (insert, upsert, delete, update), literals data source stage, and atomic execution option to Node SDK Firestore pipelines to achieve parity with Web SDK.

@wu-hui
wu-hui requested a review from a team as a code owner August 10, 2026 17:43
@product-auto-label product-auto-label Bot added the api: firestore Issues related to the Firestore API. label Aug 10, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for DML stages (insert, upsert, and literals) and an atomic execution option within Firestore pipelines, complete with updated type definitions and tests. The feedback highlights a critical transaction precedence issue where the atomic option could bypass active transactions, an options-parsing bug in the literals stage, and the need for recursive user data validation to prevent nested custom classes from bypassing checks.

Comment thread handwritten/firestore/dev/src/pipelines/pipeline-util.ts Outdated
Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts Outdated
Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts Outdated
Comment thread handwritten/firestore/dev/src/pipelines/stage.ts
@wu-hui
wu-hui force-pushed the feat-node-dml branch 2 times, most recently from 8360e1e to 8300c66 Compare October 6, 2026 15:33
Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts Outdated
Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts Outdated
Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts Outdated
Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts Outdated
Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts Outdated
Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts Outdated
…line API conventions

Follow the existing Pipeline stage convention of `stage(requiredArg)` /
variadic convenience overloads plus a single `stage(options)` overload,
where the options object carries the required params.

- literals (PipelineSource and Pipeline): remove the
  `(documents, options?)` overload; `documents` is now required in
  LiteralsStageOptions.
- update: remove the `Record<string, Expression> | Map` overload (not in
  the API proposal, no precedent, and indistinguishable at runtime from
  an options object); add `update(options: UpdateStageOptions)` with
  `transformedFields`.
- delete: add `delete(options: DeleteStageOptions)` so rawOptions can be
  provided.
- upsert: remove the `(additionalFields[], options?)` overload; use
  `upsert({additionalFields, ...})` instead.
…verloads

Follow the precedent set by database() for stages with no required
params, consistent with delete().
…tageOptions

transforms was an earlier name for additionalFields that was never
released in the Node or Web SDKs, so the deprecated alias is
unnecessary API surface.
…neSource only

literals is a source stage (LiteralsSource). It was only ever used and
tested as the first stage via PipelineSource, and the Web SDK exposes it
only on PipelineSource.
…ents

FieldValue sentinels (serverTimestamp(), increment(), arrayUnion(),
arrayRemove(), delete(), ...) cannot be represented in an encoded
pipeline. Previously they were silently dropped from literal documents
(and a document containing only sentinels failed with an INTERNAL
serialization error). Literal documents are now validated recursively
and sentinels throw the same error as the Web SDK:

  Function literals() called with invalid data. <method>() can only be
  used with update() and set() (found in field <path>)

Nested values with user data are now also validated, not just top-level
fields.
hasUserData() dereferences its argument, so a null value in a literal
document crashed _validateUserData with a TypeError.
…ents

The backend only evaluates expressions in the top-level fields of a
literal document, so nested expressions (e.g. {a: {b: add(...)}}) failed
with "Value type is not supported: FUNCTION_VALUE". Encode each document
as a top-level mapValue whose fields are converted with
valueToDefaultExpr, so nested objects and arrays become map() and array()
expressions, matching rawStage() and expression arguments.

Undefined values are now rejected unless ignoreUndefinedProperties is
enabled, preserving the previous serializer behavior.
…ic option

Describe how collection and documentIdExpression determine the target
document, that a string documentIdExpression is a field name (use
constant() for a fixed ID), that upsert requires collection when
documentIdExpression is set, and what atomic does. Behavior verified
against nightly; adds system tests for the field-name semantics and the
upsert collection requirement.
Backport documentation refinements from the Web SDK (firebase-js-sdk#10200):
- Upsert with only `collection` set auto-generates an ID when the input
  document has no ID (e.g. from literals()).
- Insert/upsert with neither `collection` nor `documentIdExpression` set
  fail for input documents that have no ID.
- update/insert/upsert method docs now point to the stage options types
  for how the target document is determined.
Port of firebase-js-sdk a6948d73f. Passing `collection: ''` to insert() or
upsert() now throws "Function insert()/upsert() cannot be called with an
empty collection path." instead of silently falling back to the input
document's parent collection.
Verified against the nightly backend: a non-atomic update skips input
documents whose target does not exist (not counted in documents_modified),
while an atomic update fails with NOT_FOUND and updates nothing. Adds
system tests for both cases.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: firestore Issues related to the Firestore API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants