Skip to content

Commit a1b1173

Browse files
tadeleshtadelesh
andauthored
Add 0.68 tcgc newsletter (#4439)
Co-authored-by: tadelesh <chenjieshi@microsoft.com>
1 parent 1eb05cd commit a1b1173

1 file changed

Lines changed: 238 additions & 0 deletions

File tree

  • packages/typespec-client-generator-core/newsletter
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# TCGC Monthly Newsletter — `@azure-tools/typespec-client-generator-core` 0.68
2+
3+
Hey everyone! This newsletter covers the latest TCGC releases (0.67.2 through 0.68.0) with the new `exact()` function for precise client naming, `serializationOptions` for body/response types, enhanced hierarchy building, and important bug fixes. As always, I welcome any and all feedback!
4+
5+
## ⭐ What's New in This Release
6+
7+
- `exact()` Function for `@clientName` ⭐ (Major Feature) — [docs](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/09renaming/#preserving-exact-casing)
8+
- `serializationOptions` on Body Parameters and Responses ⭐ (Major Feature) — [docs](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/08types/)
9+
- Enhanced `@Legacy.hierarchyBuilding` — Arbitrary Inheritance Replacement — [docs](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/11hierarchybuilding/)
10+
- `inconsistent-multiple-service-dependency` Warning — [docs](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/03client/#one-client-from-multiple-services)
11+
- Bug Fixes & Improvements
12+
13+
---
14+
15+
## ⚠️ Emitter Behavior Changes
16+
17+
Emitter authors, heads up! This release includes a **breaking change** that requires attention. See the detailed section below for migration guidance.
18+
19+
- **Multi-content-type `accept` parameter is now a string constant** — When an operation's response declares multiple content types (e.g., `Http.File<"image/png" | "image/jpeg">`), the synthetic `accept` parameter is now a single string constant (comma-joined, structured types listed first) instead of an enum. This avoids incorrectly modeling such operations as content negotiation. Use `@sharedRoute` to split an operation if real content negotiation is required.
20+
- **External alternate types no longer leak into `sdkPackage`** — Types that are only used within external alternate types are no longer included in `sdkPackage.models`, `sdkPackage.enums`, or `sdkPackage.unions`. If your emitter previously relied on these types being present in the package-level collections, they will now be absent.
21+
22+
---
23+
24+
## `exact()` Function for `@clientName` (0.68.0)
25+
26+
📖 **Docs**: [Preserving Exact Casing](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/09renaming/#preserving-exact-casing) · [`@clientName` reference](https://azure.github.io/typespec-azure/docs/libraries/typespec-client-generator-core/reference/decorators/#@Azure.ClientGenerator.Core.clientName)
27+
28+
A new `exact()` function that preserves client names **without language-specific casing transformations**. Previously, names provided via `@clientName` would still be subject to emitter-specific casing rules (e.g., `PascalCase` for C#, `snake_case` for Python). Now you can opt out of those transformations entirely.
29+
30+
### How It Works
31+
32+
Wrap the name string in `exact()` when calling `@@clientName`:
33+
34+
```typespec
35+
// Without exact — emitter may transform casing
36+
@@clientName(MyService.TestModel, "RenamedModel");
37+
38+
// With exact — name is preserved as-is, no casing transformation
39+
#suppress "experimental-feature" "using exact"
40+
@@clientName(MyService.TestModel, exact("hello_world"));
41+
```
42+
43+
Works with language scoping too:
44+
45+
```typespec
46+
// Only Python uses the exact name; other languages use the original
47+
#suppress "experimental-feature" "using exact"
48+
@@clientName(MyService.TestModel, exact("hello_world"), "python");
49+
```
50+
51+
Applies to models, properties, enums, and operations:
52+
53+
```typespec
54+
#suppress "experimental-feature" "using exact"
55+
@@clientName(MyService.TestModel.myProp, exact("my_exact_prop"));
56+
57+
#suppress "experimental-feature" "using exact"
58+
@@clientName(MyService.Status, exact("my_status_enum"));
59+
60+
#suppress "experimental-feature" "using exact"
61+
@@clientName(MyService.testOp, exact("my_exact_op"));
62+
```
63+
64+
What Emitter Authors Gain: A new `isExactName` boolean field on `SdkModelType`, `SdkEnumType`, `SdkUnionType`, and `SdkModelPropertyTypeBase`. When `isExactName` is `true`, emitters should skip their language-specific casing transformations and use the name verbatim.
65+
66+
---
67+
68+
## `serializationOptions` on Body Parameters and Responses (0.68.0)
69+
70+
📖 **Docs**: [Generated Types](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/08types/)
71+
72+
A new `serializationOptions` property on `SdkBodyParameter` and `SdkHttpResponse`/`SdkHttpErrorResponse` that tells emitters **how to serialize/deserialize the request or response body**. This is especially important for **basic (non-model) body types** — scalars like `string`, `bytes`, or `int32` — where previously emitters had no way to know the serialization format from the type alone.
73+
74+
### The Problem
75+
76+
When the body type is a model, emitters could already inspect the model's own `serializationOptions` to determine JSON/XML wire names. But when the body is a basic type (e.g., `@body body: string` or `@body body: bytes`), there's no model to inspect — emitters had to parse content-type strings themselves to figure out how to serialize.
77+
78+
### The Solution
79+
80+
`serializationOptions` is now available directly on `SdkBodyParameter` and `SdkHttpResponseBase`, providing format info regardless of body type:
81+
82+
```typescript
83+
// Emitter code — determine how to serialize a basic-type body
84+
const bodyParam = httpOperation.bodyParam;
85+
86+
if (bodyParam.serializationOptions.json) {
87+
// Body should be serialized as JSON (e.g., a raw string sent as JSON)
88+
} else if (bodyParam.serializationOptions.xml) {
89+
// Body should be serialized as XML
90+
} else if (bodyParam.serializationOptions.binary) {
91+
// Body is binary (file upload, octet-stream, etc.)
92+
const { isFile, isText, contentTypes } = bodyParam.serializationOptions.binary;
93+
}
94+
```
95+
96+
```typespec
97+
// Basic type body — emitters previously couldn't determine format
98+
op uploadRawData(@header contentType: "application/octet-stream", @body data: bytes): void;
99+
// → bodyParam.serializationOptions.binary is populated
100+
101+
op sendMessage(@header contentType: "application/json", @body message: string): void;
102+
// → bodyParam.serializationOptions.json is populated
103+
```
104+
105+
For model bodies, `serializationOptions` remains available on the model type itself and its properties (providing wire names per format), and is now **also** mirrored on the body parameter for consistency:
106+
107+
```typespec
108+
model Blob {
109+
@encodedName("application/json", "newId")
110+
id: string;
111+
}
112+
113+
op test(@body body: Blob): void;
114+
// → bodyParam.serializationOptions.json is populated
115+
// → model.properties[0].serializationOptions.json.name === "newId"
116+
```
117+
118+
What Emitter Authors Gain: A single, consistent way to determine serialization format for **all** body types — models, scalars, and files alike. No more parsing content-type strings manually for basic-type bodies.
119+
120+
---
121+
122+
## 🏗️ Enhanced `@Legacy.hierarchyBuilding` — Arbitrary Inheritance Replacement (0.68.0)
123+
124+
📖 **Docs**: [Legacy Hierarchy Building](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/11hierarchybuilding/)
125+
126+
The `@Legacy.hierarchyBuilding` decorator no longer requires the target to be a property-superset of the new base model. Properties contributed by removed intermediate parents are now **automatically lifted** onto the target, preserving the observable property set.
127+
128+
### Before (0.67.x)
129+
130+
`@Legacy.hierarchyBuilding` could only rebase to a sibling that already had all the parent's properties. Attempting to rebase to an unrelated model would fail.
131+
132+
### After (0.68.0)
133+
134+
Rebase works to arbitrary ancestor models. Missing properties from removed intermediates are lifted:
135+
136+
```typespec
137+
@discriminator("kind")
138+
model A {
139+
kind: string;
140+
}
141+
142+
alias BContent = {
143+
foo: string;
144+
};
145+
146+
model B extends A {
147+
kind: "B";
148+
...BContent;
149+
}
150+
151+
// C now inherits from B instead of A — foo is NOT required on C
152+
// because BContent is already on B
153+
@Legacy.hierarchyBuilding(B)
154+
model C extends A {
155+
kind: "C";
156+
...BContent;
157+
bar: string;
158+
}
159+
```
160+
161+
Result: `C.baseModel` becomes `B`, and `C.properties` contains only `kind` and `bar` (since `foo` is inherited from `B`).
162+
163+
What Emitter Authors Gain: More flexibility for ARM Compute-style migrations where models need to be rebased to different points in the hierarchy without redeclaring all intermediate properties.
164+
165+
---
166+
167+
## 🔔 `inconsistent-multiple-service-dependency` Warning (0.68.0)
168+
169+
📖 **Docs**: [Multi-Service Clients](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/03client/#one-client-from-multiple-services)
170+
171+
A new warning diagnostic that fires when services merged into a single client (via `autoMergeService`) declare **diverging `@useDependency` versions** for the same shared library (e.g., ARM common-types v5 vs. v6).
172+
173+
What Spec Authors Should Do: Align shared dependency versions across all services merged into one client to avoid generating duplicated or diverged models in the SDK.
174+
175+
---
176+
177+
## 🐛 Bug Fixes & Improvements
178+
179+
Related docs: [`@clientLocation`](https://azure.github.io/typespec-azure/docs/howtos/generate-client-libraries/04method/#using-clientlocation-to-control-parameter-placement) · [`@apiVersion`](https://azure.github.io/typespec-azure/docs/libraries/typespec-client-generator-core/reference/decorators/#@Azure.ClientGenerator.Core.apiVersion)
180+
181+
**`@clientLocation` with `@override` — Wrong `methodParameterSegments` (0.67.3 + 0.68.0)**
182+
183+
- Issue: Operations using both `@clientLocation` and `@override` produced incorrect `methodParameterSegments`.
184+
- Fix: [#4302](https://github.com/Azure/typespec-azure/pull/4302), [#4344](https://github.com/Azure/typespec-azure/pull/4344)
185+
186+
**`@apiVersion(false)` Ignored by `isOnClient()` (0.67.2)**
187+
188+
- Issue: `@apiVersion(false)` was ignored when other operations had already elevated an api-version parameter to client level.
189+
- Fix: [#4234](https://github.com/Azure/typespec-azure/pull/4234)
190+
191+
**Duplicate Client Entries in Multi-Service (0.67.2)**
192+
193+
- Issue: Calling `createSdkContext` multiple times or merging sub clients with the same name in multi-service cases produced duplicate client entries.
194+
- Fix: [#4253](https://github.com/Azure/typespec-azure/pull/4253)
195+
196+
**Readonly Property Usage Propagation (0.67.2)**
197+
198+
- Issue: Readonly properties didn't properly strip the `Input` flag from combined usage values, and `ignoreSubTypeStack` was unbalanced.
199+
- Fix: [#4235](https://github.com/Azure/typespec-azure/pull/4235)
200+
201+
**Error Response in Intersection Types (0.67.1)**
202+
203+
- Issue: Error responses in intersection types (e.g., `ArmAcceptedResponse & ErrorResponse`) weren't classified as exceptions, causing false `unexpected-pageable-operation-return-type` diagnostics.
204+
- Fix: [#4215](https://github.com/Azure/typespec-azure/pull/4215)
205+
206+
**`bytes` Encoding in `HttpPart` for Multipart (0.67.4)**
207+
208+
- Issue: `bytes` in `HttpPart` for `multipart/form-data` was incorrectly encoded as `base64` instead of `bytes`.
209+
- Fix: [#4345](https://github.com/Azure/typespec-azure/pull/4345)
210+
211+
**Wrong API Version Param Judgement (0.68.0)**
212+
213+
- Issue: A body model property named `apiVersion`/`api-version` was incorrectly flagged as `isApiVersionParam` with a service-derived `clientDefaultValue`. Only operation parameters should be considered API version parameters.
214+
- Fix: [#4341](https://github.com/Azure/typespec-azure/pull/4341), [#4386](https://github.com/Azure/typespec-azure/pull/4386)
215+
216+
**`@responseAsBool` on HEAD Operations (0.68.0)**
217+
218+
- Issue: `@responseAsBool` incorrectly set `bodyType` on HEAD operation HTTP responses.
219+
- Fix: [#4343](https://github.com/Azure/typespec-azure/pull/4343)
220+
221+
**External Alternate Types Leaking into Package (0.68.0)**
222+
223+
- Issue: Types only used within external alternate types were incorrectly included in `sdkPackage` models, enums, or unions.
224+
- Fix: [#4236](https://github.com/Azure/typespec-azure/pull/4236)
225+
226+
---
227+
228+
## 🎉 The Bottom Line
229+
230+
The headline feature is **`exact()`** — a simple but powerful addition that lets spec authors preserve client names exactly as written, bypassing emitter casing transformations. This is especially useful for names with deliberate casing (acronyms, legacy names, cross-language consistency).
231+
232+
**`serializationOptions`** on body parameters and responses gives emitters a clear, format-aware contract for serialization — no more inferring JSON vs. XML from content-type strings.
233+
234+
The **breaking change** to multi-content-type `accept` parameters (string constant instead of enum) properly distinguishes "accept all these types" from true content negotiation. If you have emitter logic that pattern-matches on enum-typed accept parameters, update it to handle string constants.
235+
236+
Special thanks to all emitter authors for your continued collaboration and feedback! 🙌
237+
238+
Thanks, @Chenjie and @Isabella

0 commit comments

Comments
 (0)