Repository navigation
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
Open
feat(firestore): add DML stages, literals source, and atomic execution option to Node SDK pipelines#9118wu-hui wants to merge 19 commits into
wu-hui wants to merge 19 commits into
Conversation
Contributor
There was a problem hiding this comment.
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.
4 tasks done
…erals source, and atomic execution option to Node SDK pipelines
…cution and test atomic: false
wu-hui
force-pushed
the
feat-node-dml
branch
2 times, most recently
from
October 6, 2026 15:33
8360e1e to
8300c66
Compare
Merged
…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.
MarkDuckworth
approved these changes
Oct 19, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.