Skip to content

Commit ae1ca3f

Browse files
committed
update
1 parent 9662ed8 commit ae1ca3f

62 files changed

Lines changed: 18627 additions & 16 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/tagging.yml

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ name: tagging
44
on:
55
# Manual dispatch.
66
workflow_dispatch:
7-
inputs:
8-
package:
9-
description: 'Package to tag (leave empty to tag all packages with pending releases).'
10-
required: false
11-
type: string
12-
default: ''
7+
# No inputs are required for the manual dispatch.
138

149
# NOTE: Temporarily disable automated releases.
1510
#
@@ -66,10 +61,12 @@ jobs:
6661
env:
6762
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
6863
GITHUB_REPOSITORY: ${{ github.repository }}
69-
PACKAGE: ${{ inputs.package }}
70-
run: |
71-
if [ -n "$PACKAGE" ]; then
72-
uv run --locked tagging.py --package "$PACKAGE"
73-
else
74-
uv run --locked tagging.py
75-
fi
64+
run: uv run --locked tagging.py
65+
66+
- name: Upload created tags artifact
67+
if: always()
68+
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
69+
with:
70+
name: created-tags
71+
path: created_tags.json
72+
if-no-files-found: ignore

README.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,120 @@
99
> - **Breaking changes may occur at any time**
1010
> - **APIs are experimental and unstable**
1111
> - **Use for development and testing only**
12+
13+
## Design Notes
14+
15+
### FieldMask — Deferred Ergonomics Decisions
16+
17+
The current `FieldMask` implementation validates paths against a per-message
18+
schema inside `FieldMask.build`, throws on mismatch, and stores the
19+
wire-format paths privately so `toString()` produces the server-facing
20+
comma-separated string. Construction entry point today is a **per-message
21+
factory function** generated alongside each message — e.g.
22+
`alertFieldMask('displayName', 'condition.op')` — which supplies the schema
23+
and message name and delegates to `FieldMask.build`. This section records
24+
two refinements we've discussed but deferred; they do not change the
25+
validation semantics, only the call-site shape.
26+
27+
#### Q1 — Call-site ergonomics
28+
29+
**Current (Option C, per-message factory):**
30+
31+
```ts
32+
import {alertFieldMask} from '@databricks/sdk-alerts/v1';
33+
const mask = alertFieldMask('displayName', 'condition.op');
34+
```
35+
36+
- Pros: best discoverability (auto-complete on import), single-argument call,
37+
error messages name the target message, and users never think about
38+
schemas or message names.
39+
- Cons: one generated factory per message (~60+ across the SDK). Each is a
40+
thin one-liner, but they multiply with every new message.
41+
42+
**Option A — raw `FieldMask.build` at the call site:**
43+
44+
```ts
45+
import {FieldMask} from '@databricks/sdk-core/wkt';
46+
import {Alert, alertFieldMaskSchema} from '@databricks/sdk-alerts/v1';
47+
48+
const mask = FieldMask.build<Alert>(
49+
['displayName', 'condition.op'],
50+
alertFieldMaskSchema,
51+
);
52+
```
53+
54+
- Pros: zero helper functions anywhere. Only `FieldMask.build` exists.
55+
- Cons: two-argument low-level call at every usage site. Users must
56+
import the schema explicitly and know which schema pairs with which
57+
type.
58+
59+
**Option B — one generic helper in `sdk-core`:**
60+
61+
```ts
62+
import {fieldMask} from '@databricks/sdk-core/wkt';
63+
import {Alert} from '@databricks/sdk-alerts/v1';
64+
65+
const mask = fieldMask(Alert, 'displayName', 'condition.op');
66+
```
67+
68+
- Pros: a single `fieldMask(...)` replaces the ~60+ per-message factories.
69+
`Alert` supplies both the schema and the message name as properties on
70+
itself, so the call site stays one argument plus paths.
71+
- Cons: requires `Alert` the import to be **both** a TypeScript type and a
72+
runtime descriptor value on the same name. See Q2 below.
73+
74+
#### Q2 — Interface + const declaration merging on the message name
75+
76+
A TypeScript pattern that lets one exported identifier occupy both the
77+
type-space and the value-space:
78+
79+
```ts
80+
// Type — describes instance shape. Zero runtime cost.
81+
export interface Alert {
82+
displayName?: string;
83+
condition?: Condition;
84+
}
85+
86+
// Runtime value — carries the schema under the same name.
87+
export const Alert: MessageDescriptor<Alert> = {
88+
fieldMaskSchema: {
89+
displayName: {wire: 'display_name'},
90+
condition: {wire: 'condition', children: () => Condition.fieldMaskSchema},
91+
},
92+
};
93+
```
94+
95+
Usage after this change:
96+
97+
```ts
98+
const a: Alert = {displayName: 'foo'}; // Alert as a type (literal shape)
99+
const s = Alert.fieldMaskSchema; // Alert as a value (runtime)
100+
const mask = fieldMask(Alert, 'displayName'); // Option B unblocked
101+
```
102+
103+
TypeScript supports this via
104+
[declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html).
105+
`interface X` occupies type-space, `const X` occupies value-space; they do
106+
not collide. The same pattern shows up in `lib.dom.d.ts`, `Promise`, and
107+
various DI libraries.
108+
109+
- Pros: single import, natural `Alert.fieldMaskSchema` access, enables
110+
Option B without asking users to remember a separate `AlertSchema` name.
111+
- Cons: the pattern is less common in everyday TS and can surprise readers
112+
who expect classes for anything with static-like members. The alternative
113+
is to use a distinct name — e.g. `AlertSchema` or `AlertDescriptor` — for
114+
the runtime value, at the cost of one extra identifier to learn per
115+
message.
116+
117+
#### Why we haven't landed Q1/Q2 yet
118+
119+
Both are call-site ergonomics refactors; neither changes the validation
120+
semantics or the per-message schema generation. We want the current
121+
`FieldMask.build` path (validate, translate, store wire paths privately,
122+
`toString()` joins) to settle before adjusting the call-site shape, so
123+
the two axes of change don't churn simultaneously. When we revisit, the
124+
likely landing is **Option B + Option Q2** together — one generic
125+
`fieldMask()` plus the interface+const merge, which most closely matches
126+
what similar TypeScript validation libraries (Zod, Valibot, TypeBox, etc.)
127+
expose while staying consistent with the SDK's existing interface-first
128+
convention for message types.

0 commit comments

Comments
 (0)