Skip to content

Commit d650bb5

Browse files
v-jiaodiMaryGaoMary Gao
authored
Fix LRO operation status model not generation issue (#3434)
* Verify that the library option is set to true for @azure-rest/azure-widget-analytics * add ut * Fix the operation status model not generation issue * Fix the lint issue * Remove the isAzureCoreLroType logic * remove smoke case --------- Co-authored-by: Mary Gao <yanmeigao1210@gmail.com> Co-authored-by: Mary Gao <marygao@microsoft.com>
1 parent 1afbdd2 commit d650bb5

3 files changed

Lines changed: 202 additions & 35 deletions

File tree

packages/typespec-ts/src/modular/emitModels.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,7 @@ import path from "path";
4646
import { refkey } from "../framework/refkey.js";
4747
import { useContext } from "../contextManager.js";
4848
import { isMetadata, isOrExtendsHttpFile } from "@typespec/http";
49-
import {
50-
isAzureCoreErrorType,
51-
isAzureCoreLroType
52-
} from "../utils/modelUtils.js";
49+
import { isAzureCoreErrorType } from "../utils/modelUtils.js";
5350
import { isExtensibleEnum } from "./type-expressions/get-enum-expression.js";
5451
import {
5552
getAllDiscriminatedValues,
@@ -109,9 +106,6 @@ export function emitTypes(
109106
if (!isGenerableType(type)) {
110107
continue;
111108
}
112-
if (isAzureCoreLroType(type.__raw)) {
113-
continue;
114-
}
115109

116110
const namespaces = getModelNamespaces(context, type);
117111
const filepath = getModelsPath(sourceRoot, namespaces);

packages/typespec-ts/src/utils/modelUtils.ts

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,14 +1708,6 @@ export function trimUsage(model: any) {
17081708
return ordered;
17091709
}
17101710

1711-
export function buildCoreTypeInfo(program: Program, t?: Type) {
1712-
return isAzureCoreErrorType(program, t)
1713-
? "ErrorType"
1714-
: isAzureCoreLroType(t)
1715-
? "LroType"
1716-
: undefined;
1717-
}
1718-
17191711
export function isAzureCoreErrorType(program: Program, t?: Type): boolean {
17201712
if (!t || t.kind !== "Model") {
17211713
return false;
@@ -1731,26 +1723,6 @@ export function isAzureCoreErrorType(program: Program, t?: Type): boolean {
17311723
return isAzureCoreFoundationsNamespace(effective);
17321724
}
17331725

1734-
// Check if the type in the Azure.Core.Foundations has an LRO type in core
1735-
export function isAzureCoreLroType(t?: Type): boolean {
1736-
if (
1737-
!(
1738-
((t?.kind === "Enum" || t?.kind === "Union") &&
1739-
["operationstate"].includes((t.name ?? "").toLowerCase())) ||
1740-
(t?.kind === "Model" &&
1741-
["resourceoperationstatus", "operationstatus"].includes(
1742-
t.name.toLowerCase()
1743-
))
1744-
)
1745-
) {
1746-
return false;
1747-
}
1748-
return (
1749-
isAzureCoreFoundationsNamespace(t) ||
1750-
isAzureCoreFoundationsNamespace(t, true)
1751-
);
1752-
}
1753-
17541726
function isAzureCoreFoundationsNamespace(
17551727
t?: Type,
17561728
skipFoundation: boolean = false
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# should handle Azure Core LRO operations without placeholder issues
2+
3+
Azure Core LRO operations should generate proper TypeScript code without unresolved placeholders.
4+
5+
## TypeSpec
6+
7+
```tsp
8+
using Azure.Core.Traits;
9+
10+
/** A widget. */
11+
@resource("widgets")
12+
model WidgetSuite {
13+
/** The widget name. */
14+
@key
15+
name: string;
16+
17+
/** The ID of the widget's manufacturer. */
18+
manufacturerId: string;
19+
20+
/** The faked shared model. */
21+
sharedModel?: FakedSharedModel;
22+
}
23+
24+
/** Faked shared model */
25+
model FakedSharedModel {
26+
/** The tag. */
27+
tag: string;
28+
29+
/** The created date. */
30+
createdAt: offsetDateTime;
31+
}
32+
33+
alias ServiceTraits = Azure.Core.Traits.SupportsRepeatableRequests &
34+
Azure.Core.Traits.SupportsConditionalRequests &
35+
Azure.Core.Traits.SupportsClientRequestId;
36+
37+
alias Operations = Azure.Core.ResourceOperations<ServiceTraits>;
38+
39+
interface Widgets {
40+
@doc("Get the status of a long-running operation on widgets.")
41+
getWidgetOperationStatus is Operations.GetResourceOperationStatus<WidgetSuite>;
42+
}
43+
```
44+
45+
The config would be like:
46+
47+
```yaml
48+
needAzureCore: true
49+
```
50+
51+
## Operations
52+
53+
```ts operations
54+
import { TestingContext as Client } from "./index.js";
55+
import {
56+
ResourceOperationStatusWidgetSuiteWidgetSuiteError,
57+
resourceOperationStatusWidgetSuiteWidgetSuiteErrorDeserializer,
58+
} from "../models/models.js";
59+
import { expandUrlTemplate } from "../static-helpers/urlTemplate.js";
60+
import { GetWidgetOperationStatusOptionalParams } from "./options.js";
61+
import {
62+
StreamableMethod,
63+
PathUncheckedResponse,
64+
createRestError,
65+
operationOptionsToRequestParameters,
66+
} from "@azure-rest/core-client";
67+
68+
export function _getWidgetOperationStatusSend(
69+
context: Client,
70+
apiVersion: string,
71+
name: string,
72+
operationId: string,
73+
options: GetWidgetOperationStatusOptionalParams = { requestOptions: {} },
74+
): StreamableMethod {
75+
const path = expandUrlTemplate(
76+
"/widgets/{name}/operations/{operationId}{?api%2Dversion}",
77+
{
78+
name: name,
79+
operationId: operationId,
80+
"api%2Dversion": apiVersion,
81+
},
82+
{
83+
allowReserved: options?.requestOptions?.skipUrlEncoding,
84+
},
85+
);
86+
return context
87+
.path(path)
88+
.get({
89+
...operationOptionsToRequestParameters(options),
90+
headers: {
91+
accept: "application/json",
92+
...options.requestOptions?.headers,
93+
},
94+
});
95+
}
96+
97+
export async function _getWidgetOperationStatusDeserialize(
98+
result: PathUncheckedResponse,
99+
): Promise<ResourceOperationStatusWidgetSuiteWidgetSuiteError> {
100+
const expectedStatuses = ["200"];
101+
if (!expectedStatuses.includes(result.status)) {
102+
throw createRestError(result);
103+
}
104+
105+
return resourceOperationStatusWidgetSuiteWidgetSuiteErrorDeserializer(
106+
result.body,
107+
);
108+
}
109+
110+
/** Get the status of a long-running operation on widgets. */
111+
export async function getWidgetOperationStatus(
112+
context: Client,
113+
apiVersion: string,
114+
name: string,
115+
operationId: string,
116+
options: GetWidgetOperationStatusOptionalParams = { requestOptions: {} },
117+
): Promise<ResourceOperationStatusWidgetSuiteWidgetSuiteError> {
118+
const result = await _getWidgetOperationStatusSend(
119+
context,
120+
apiVersion,
121+
name,
122+
operationId,
123+
options,
124+
);
125+
return _getWidgetOperationStatusDeserialize(result);
126+
}
127+
```
128+
129+
Generate the models
130+
131+
```ts models
132+
import { ErrorModel } from "@azure-rest/core-client";
133+
134+
/** Provides status details for long running operations. */
135+
export interface ResourceOperationStatusWidgetSuiteWidgetSuiteError {
136+
/** The unique ID of the operation. */
137+
id: string;
138+
/** The status of the operation */
139+
status: OperationState;
140+
/** Error object that describes the error when status is "Failed". */
141+
error?: ErrorModel;
142+
/** The result of the operation. */
143+
result?: WidgetSuite;
144+
}
145+
146+
export function resourceOperationStatusWidgetSuiteWidgetSuiteErrorDeserializer(
147+
item: any,
148+
): ResourceOperationStatusWidgetSuiteWidgetSuiteError {
149+
return {
150+
id: item["id"],
151+
status: item["status"],
152+
error: !item["error"] ? item["error"] : item["error"],
153+
result: !item["result"]
154+
? item["result"]
155+
: widgetSuiteDeserializer(item["result"]),
156+
};
157+
}
158+
159+
/** Enum describing allowed operation states. */
160+
export type OperationState =
161+
| "NotStarted"
162+
| "Running"
163+
| "Succeeded"
164+
| "Failed"
165+
| "Canceled";
166+
167+
/** A widget. */
168+
export interface WidgetSuite {
169+
/** The widget name. */
170+
name: string;
171+
/** The ID of the widget's manufacturer. */
172+
manufacturerId: string;
173+
/** The faked shared model. */
174+
sharedModel?: FakedSharedModel;
175+
}
176+
177+
export function widgetSuiteDeserializer(item: any): WidgetSuite {
178+
return {
179+
name: item["name"],
180+
manufacturerId: item["manufacturerId"],
181+
sharedModel: !item["sharedModel"]
182+
? item["sharedModel"]
183+
: fakedSharedModelDeserializer(item["sharedModel"]),
184+
};
185+
}
186+
187+
/** Faked shared model */
188+
export interface FakedSharedModel {
189+
/** The tag. */
190+
tag: string;
191+
/** The created date. */
192+
createdAt: string;
193+
}
194+
195+
export function fakedSharedModelDeserializer(item: any): FakedSharedModel {
196+
return {
197+
tag: item["tag"],
198+
createdAt: item["createdAt"],
199+
};
200+
}
201+
```

0 commit comments

Comments
 (0)