Skip to content

Update typed FieldMask in sdk-core#101

Merged
parthban-db merged 1 commit into
mainfrom
parthban-db/stack/field-mask-sdk-core
Apr 22, 2026
Merged

Update typed FieldMask in sdk-core#101
parthban-db merged 1 commit into
mainfrom
parthban-db/stack/field-mask-sdk-core

Conversation

@parthban-db
Copy link
Copy Markdown
Contributor

@parthban-db parthban-db commented Apr 22, 2026

🥞 Stacked PR

Use this link to review incremental changes.


Summary

Update the FieldMask<T> in @databricks/sdk-core/wkt. FieldMask.build validates paths against a per-message schema, translates them to wire format, and stores the result privately. toString() serializes to the comma-separated wire string the server expects.

Why

Databricks accepts field-mask paths in proto snake_case, but generated TS interfaces use camelCase. The existing FieldMask didn't translate or validate — typos went silently to the server. This is the runtime foundation the generator needs; the follow-up PR emits the per-message schemas and factories that call FieldMask.build.

Why validation is at runtime, not compile time

A compile-time FieldPaths<T> conditional type (computing the string-literal union of valid paths for each generated interface) was explored and rejected. TypeScript's conditional-type evaluation has a hard recursion depth limit — any proto message that references itself or forms a cycle through another message (common in Databricks' schemas: Node { child: Node }, A → B → A) triggers TS2589: Type instantiation is excessively deep and possibly infinite. Verified by probing against the real sdk-js tsconfig. Because we can't express a complete set of valid paths at the type level for the schemas we actually ship, FieldMask.build walks the schema at runtime and throws on a mismatch instead. The schema itself is a plain runtime object with lazy () => FieldMaskSchema child references, which keeps recursive and mutually-recursive protos describable as finite graphs.

What changed

Interface changes

  • FieldMask<T = unknown> — private constructor, @internal static build<T>(paths, schema) as the sole entry point, toString(): string returning the joined wire paths. Phantom T distinguishes masks across messages at compile time.
  • FieldMaskSchema, FieldMaskSchemaField — new exports. The shape the generator emits per message; children?: () => FieldMaskSchema keeps recursive/mutual-recursive protos cycle-safe.
  • Removed: FieldPaths<T>, FieldMask.of(...), FieldMask.append(...). See the "Why validation is at runtime" note above for the rationale.

Behavioral changes

FieldMask.build throws on an unknown path segment or descent past a scalar leaf. Before, any string was accepted.

Internal changes

walkFieldMaskPath and normalize are module-private in packages/core/src/wkt/fieldmask.ts.

How is this tested?

Table-driven tests (it.each) in packages/core/tests/wkt/fieldmask.test.ts:

  • Valid paths translate and serialize (8 cases): flat, nested, deep, multi-path sort, dedup, parent subsumption, empty input, self-cycle at arbitrary depth.
  • Invalid paths throw (3 cases): unknown top-level, unknown nested, descent past scalar.

@github-actions
Copy link
Copy Markdown

Please ensure that the NEXT_CHANGELOG.md file is updated with any relevant changes.
If this is not necessary for your PR, please include the following in your PR description:
NO_CHANGELOG=true
and rerun the job.

@parthban-db parthban-db force-pushed the parthban-db/stack/field-mask-sdk-core branch 2 times, most recently from fe1ee1c to 20e3093 Compare April 22, 2026 12:25
@parthban-db parthban-db changed the title Add typed FieldMask to sdk-core Update typed FieldMask to sdk-core Apr 22, 2026
@parthban-db parthban-db changed the title Update typed FieldMask to sdk-core Update typed FieldMask in sdk-core Apr 22, 2026
@parthban-db parthban-db mentioned this pull request Apr 22, 2026
Copy link
Copy Markdown
Contributor

@tejaskochar-db tejaskochar-db left a comment

Choose a reason for hiding this comment

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

LGTM

@parthban-db parthban-db added this pull request to the merge queue Apr 22, 2026
Merged via the queue into main with commit 6dd575d Apr 22, 2026
9 of 15 checks passed
@parthban-db parthban-db deleted the parthban-db/stack/field-mask-sdk-core branch April 22, 2026 14:22
@parthban-db parthban-db restored the parthban-db/stack/field-mask-sdk-core branch April 22, 2026 16:29
@parthban-db parthban-db mentioned this pull request Apr 22, 2026
@parthban-db parthban-db deleted the parthban-db/stack/field-mask-sdk-core branch May 12, 2026 15:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants