Skip to content

Commit 47adf85

Browse files
MaryGaoqiaozha
andauthored
Support client request id modular and small fixes (#1985)
* Ignore the custom client-request-id header in modular * Remove the only item * Remove the debug options * Change test case namings * Revert changes * update changes * update the test cases * update the code * update the code to fix modular issue * Regen smoke and integration testing * update test cases * update the test cases * update the isunexpected helper * Fix int test issues * Fix the test issue * Fix this test issue * update the test cases * Add more ignored headers * Refactoring * Enable azure core cases * adjust the positions * Update .vscode/launch.json * fix the issue bugs * Update packages/typespec-ts/src/index.ts * Fix small issue * Remove useless codes * Revert the changes for default response support * Regenerate codes * Revert changes in rlc int test * Remove console.log code lines * Update packages/typespec-ts/test/integration/encodeDatetime.spec.ts * Update packages/typespec-ts/test/integration/encodeDatetime.spec.ts * Update packages/typespec-ts/test/integration/encodeDatetime.spec.ts * Update packages/typespec-ts/test/integration/encodeDatetime.spec.ts * Update packages/typespec-ts/test/integration/encodeDatetime.spec.ts * Revert changes * fix lint issues * Revert changes * Update packages/typespec-ts/src/modular/helpers/operationHelpers.ts Co-authored-by: Qiaoqiao Zhang <55688292+qiaozha@users.noreply.github.com> * update the order --------- Co-authored-by: Qiaoqiao Zhang <55688292+qiaozha@users.noreply.github.com>
1 parent 62cd637 commit 47adf85

48 files changed

Lines changed: 829 additions & 196 deletions

Some content is hidden

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

packages/rlc-common/src/buildObjectTypes.ts

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ export function buildObjectInterfaces(
3333
const objectInterfaces: InterfaceDeclarationStructure[] = [];
3434

3535
for (const objectSchema of objectSchemas) {
36-
if (objectSchema.alias || objectSchema.outputAlias) {
36+
if (
37+
objectSchema.alias ||
38+
objectSchema.outputAlias ||
39+
objectSchema.fromCore
40+
) {
3741
continue;
3842
}
3943
const baseName = getObjectBaseName(objectSchema, schemaUsage);
@@ -417,18 +421,40 @@ export function getPropertySignature(
417421
importedModels: Set<string>
418422
): PropertySignatureStructure {
419423
const propertyName = property.name;
420-
421424
const description = property.description;
422-
let type =
423-
generateForOutput(schemaUsage, property.usage) && property.outputTypeName
424-
? property.outputTypeName
425-
: property.typeName
426-
? property.typeName
427-
: property.type;
428-
if (property.typeName && property.fromCore) {
429-
importedModels.add(property.typeName);
425+
let type;
426+
const hasCoreInArray =
427+
property.type === "array" &&
428+
(property as any).items &&
429+
(property as any).items.fromCore;
430+
const hasCoreInRecord =
431+
property.type === "dictionary" &&
432+
(property as any).additionalProperties &&
433+
(property as any).additionalProperties.fromCore;
434+
if (hasCoreInArray && property.typeName) {
435+
type = property.typeName;
436+
importedModels.add(
437+
(property as any).items.typeName ?? (property as any).items.name
438+
);
439+
} else if (hasCoreInRecord && property.typeName) {
430440
type = property.typeName;
441+
importedModels.add(
442+
(property as any).additionalProperties.typeName ??
443+
(property as any).additionalProperties.name
444+
);
445+
} else {
446+
type =
447+
generateForOutput(schemaUsage, property.usage) && property.outputTypeName
448+
? property.outputTypeName
449+
: property.typeName
450+
? property.typeName
451+
: property.type;
452+
if (property.typeName && property.fromCore) {
453+
importedModels.add(property.typeName);
454+
type = property.typeName;
455+
}
431456
}
457+
432458
return {
433459
name: propertyName,
434460
...(description && { docs: [{ description }] }),

packages/typespec-test/test/healthinsight/generated/typespec-ts/review/health-insights-clinicalmatching.api.md

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import { Client } from '@azure-rest/core-client';
88
import { ClientOptions } from '@azure-rest/core-client';
99
import { CreateHttpPollerOptions } from '@azure/core-lro';
10+
import { ErrorModel } from '@azure-rest/core-client';
1011
import { ErrorResponse } from '@azure-rest/core-client';
1112
import { HttpResponse } from '@azure-rest/core-client';
1213
import { KeyCredential } from '@azure/core-auth';
@@ -234,15 +235,6 @@ export interface DocumentContent {
234235
value: string;
235236
}
236237

237-
// @public
238-
export interface ErrorModelOutput {
239-
code: string;
240-
details?: Array<ErrorModelOutput>;
241-
innererror?: InnerErrorOutput;
242-
message: string;
243-
target?: string;
244-
}
245-
246238
// @public
247239
export interface ExtendedClinicalCodedElementOutput {
248240
category?: string;
@@ -306,12 +298,6 @@ export type HealthInsightsClinicalMatchingClient = Client & {
306298
path: Routes;
307299
};
308300

309-
// @public
310-
export interface InnerErrorOutput {
311-
code?: string;
312-
innererror?: InnerErrorOutput;
313-
}
314-
315301
// @public (undocumented)
316302
export function isUnexpected(response: GetJob200Response | GetJobDefaultResponse): response is GetJobDefaultResponse;
317303

@@ -391,7 +377,7 @@ export interface TrialMatcherPatientResultOutput {
391377
// @public
392378
export interface TrialMatcherResultOutput {
393379
readonly createdDateTime: string;
394-
readonly errors?: Array<ErrorModelOutput>;
380+
readonly errors?: Array<ErrorModel>;
395381
readonly expirationDateTime: string;
396382
readonly jobId: string;
397383
readonly lastUpdateDateTime: string;

packages/typespec-test/test/healthinsight/generated/typespec-ts/src/outputModels.ts

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT license.
33

4+
import { ErrorModel } from "@azure-rest/core-client";
5+
46
/** The response for the Trial Matcher request. */
57
export interface TrialMatcherResultOutput {
68
/** A processing job identifier. */
@@ -18,33 +20,11 @@ export interface TrialMatcherResultOutput {
1820
*/
1921
readonly status: string;
2022
/** An array of errors, if any errors occurred during the processing job. */
21-
readonly errors?: Array<ErrorModelOutput>;
23+
readonly errors?: Array<ErrorModel>;
2224
/** The inference results for the Trial Matcher request. */
2325
readonly results?: TrialMatcherResultsOutput;
2426
}
2527

26-
/** The error object. */
27-
export interface ErrorModelOutput {
28-
/** One of a server-defined set of error codes. */
29-
code: string;
30-
/** A human-readable representation of the error. */
31-
message: string;
32-
/** The target of the error. */
33-
target?: string;
34-
/** An array of details about specific errors that led to this reported error. */
35-
details?: Array<ErrorModelOutput>;
36-
/** An object containing more specific information than the current object about the error. */
37-
innererror?: InnerErrorOutput;
38-
}
39-
40-
/** An object containing more specific information about the error. As per Microsoft One API guidelines - https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md#7102-error-condition-responses. */
41-
export interface InnerErrorOutput {
42-
/** One of a server-defined set of error codes. */
43-
code?: string;
44-
/** Inner error. */
45-
innererror?: InnerErrorOutput;
46-
}
47-
4828
/** The inference results for the Trial Matcher request. */
4929
export interface TrialMatcherResultsOutput {
5030
/** Results for the patients given in the request. */

packages/typespec-ts/src/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import { join } from "path";
5151
import { GenerationDirDetail, SdkContext } from "./utils/interfaces.js";
5252
import { transformRLCOptions } from "./transform/transfromRLCOptions.js";
5353
import { ModularCodeModel } from "./modular/modularCodeModel.js";
54+
import { getClientName } from "@azure-tools/rlc-common";
5455

5556
export * from "./lib.js";
5657

@@ -119,7 +120,10 @@ export async function $onEmit(context: EmitContext) {
119120
const rlcModels = await transformRLCModel(client, dpgContext);
120121
rlcCodeModels.push(rlcModels);
121122
serviceNameToRlcModelsMap.set(client.service.name, rlcModels);
122-
needUnexpectedHelper.set(client.name, hasUnexpectedHelper(rlcModels));
123+
needUnexpectedHelper.set(
124+
getClientName(rlcModels),
125+
hasUnexpectedHelper(rlcModels)
126+
);
123127

124128
await emitModels(rlcModels, program);
125129
await emitContentByBuilder(program, buildClientDefinitions, rlcModels);
@@ -162,9 +166,7 @@ export async function $onEmit(context: EmitContext) {
162166
buildModels(modularCodeModel, subClient);
163167
buildModelsOptions(modularCodeModel, subClient);
164168
const hasClientUnexpectedHelper =
165-
needUnexpectedHelper.get(
166-
subClient.rlcClientName.replace("Context", "Client")
167-
) ?? false;
169+
needUnexpectedHelper.get(subClient.rlcClientName) ?? false;
168170
buildOperationFiles(
169171
dpgContext,
170172
modularCodeModel,

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

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import {
4242
import {
4343
getAuthentication,
4444
getHeaderFieldName,
45-
getHttpOperation,
4645
getPathParamName,
4746
getQueryParamName,
4847
getServers,
@@ -53,7 +52,8 @@ import {
5352
HttpServer,
5453
isStatusCode,
5554
HttpOperation,
56-
isHeader
55+
isHeader,
56+
getHttpOperation
5757
} from "@typespec/http";
5858
import { getAddedOnVersions } from "@typespec/versioning";
5959
import {
@@ -80,7 +80,10 @@ import {
8080
Type as HrlcType,
8181
Header
8282
} from "./modularCodeModel.js";
83-
import { getEnrichedDefaultApiVersion } from "../utils/modelUtils.js";
83+
import {
84+
getEnrichedDefaultApiVersion,
85+
isAzureCoreErrorType
86+
} from "../utils/modelUtils.js";
8487
import { camelToSnakeCase, toCamelCase } from "../utils/casingUtils.js";
8588
import {
8689
RLCModel,
@@ -90,7 +93,8 @@ import {
9093
} from "@azure-tools/rlc-common";
9194
import {
9295
getOperationGroupName,
93-
getOperationName
96+
getOperationName,
97+
isIgnoredHeaderParam
9498
} from "../utils/operationUtil.js";
9599
import { SdkContext } from "../utils/interfaces.js";
96100
import { Project } from "ts-morph";
@@ -554,23 +558,6 @@ function emitResponseHeaders(
554558
return retval;
555559
}
556560

557-
function isAzureCoreErrorType(t?: Type): boolean {
558-
if (
559-
t?.kind !== "Model" ||
560-
!["Error", "ErrorResponse", "InnerError"].includes(t.name)
561-
)
562-
return false;
563-
const namespaces = ".Azure.Core.Foundations".split(".");
564-
while (
565-
namespaces.length > 0 &&
566-
(t?.kind === "Model" || t?.kind === "Namespace") &&
567-
t.namespace?.name === namespaces.pop()
568-
) {
569-
t = t.namespace;
570-
}
571-
return namespaces.length == 0;
572-
}
573-
574561
function emitResponse(
575562
context: SdkContext,
576563
response: HttpOperationResponse,
@@ -753,6 +740,9 @@ function emitBasicOperation(
753740
});
754741

755742
for (const param of httpOperation.parameters.parameters) {
743+
if (isIgnoredHeaderParam(param)) {
744+
continue;
745+
}
756746
const emittedParam = emitParameter(context, param, "Method");
757747
if (isApiVersion(context, param) && apiVersionParam === undefined) {
758748
apiVersionParam = emittedParam;

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export function buildModels(
1515
// We are generating both models and enums here
1616
const coreClientTypes = new Set<string>();
1717
const models = codeModel.types.filter(
18-
(t) => (t.type === "model" || t.type === "enum") && !isAzureCoreError(t)
18+
(t) =>
19+
(t.type === "model" || t.type === "enum") && !isAzureCoreErrorSdkType(t)
1920
);
2021

2122
// Skip to generate models.ts if there is no any models
@@ -78,8 +79,8 @@ export function buildModels(
7879
properties: properties.map((p) => {
7980
const propertyMetadata = getType(p.type);
8081
let propertyTypeName = propertyMetadata.name;
81-
if (isAzureCoreError(p.type)) {
82-
propertyTypeName = isAzureCoreError(p.type)
82+
if (isAzureCoreErrorSdkType(p.type)) {
83+
propertyTypeName = isAzureCoreErrorSdkType(p.type)
8384
? getCoreClientErrorType(propertyTypeName)
8485
: propertyTypeName;
8586
}
@@ -122,10 +123,12 @@ export function buildModels(
122123
return modelsFile;
123124
}
124125

125-
function isAzureCoreError(t: Type) {
126+
function isAzureCoreErrorSdkType(t: Type) {
126127
return (
127128
t.name &&
128-
["Error", "InnerError"].includes(t.name) &&
129+
["error", "errormodel", "innererror", "errorresponse"].includes(
130+
t.name.toLowerCase()
131+
) &&
129132
t.isCoreErrorType === true
130133
);
131134
}

packages/typespec-ts/src/modular/helpers/operationHelpers.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export function getDeserializePrivateFunction(
9090
): OptionalKind<FunctionDeclarationStructure> {
9191
const { name } = getOperationName(operation);
9292

93-
let parameters: OptionalKind<ParameterDeclarationStructure>[] = [
93+
const parameters: OptionalKind<ParameterDeclarationStructure>[] = [
9494
{
9595
name: "result",
9696
type: getRLCResponseType(operation.rlcResponse)
@@ -103,14 +103,6 @@ export function getDeserializePrivateFunction(
103103
if (response?.type?.type) {
104104
returnType = buildType(response.type.name, response.type);
105105
} else {
106-
if (!needUnexpectedHelper) {
107-
parameters = [
108-
{
109-
name: "_result",
110-
type: getRLCResponseType(operation.rlcResponse)
111-
}
112-
];
113-
}
114106
returnType = { name: "", type: "void" };
115107
}
116108

@@ -128,6 +120,24 @@ export function getDeserializePrivateFunction(
128120
"throw result.body",
129121
"}"
130122
);
123+
} else {
124+
const validStatus = [
125+
...new Set(
126+
operation.responses
127+
.flatMap((r) => r.statusCodes)
128+
.filter((s) => s !== "default")
129+
)
130+
];
131+
132+
if (validStatus.length > 0) {
133+
statements.push(
134+
`if(${validStatus
135+
.map((s) => `result.status !== "${s}"`)
136+
.join(" || ")}){`,
137+
"throw result.body",
138+
"}"
139+
);
140+
}
131141
}
132142

133143
if (response?.type?.type === "any") {

packages/typespec-ts/src/transform/transformResponses.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,10 @@ function transformBody(
182182
const bodySchema = getSchemaForType(dpgContext, body!.type, [
183183
SchemaContext.Output
184184
]) as Schema;
185-
if (bodySchema.fromCore) {
186-
fromCore = true;
187-
}
185+
fromCore = bodySchema.fromCore ?? false;
188186
const bodyType = getTypeName(bodySchema);
189187
const importedNames = getImportedModelName(bodySchema);
190-
if (importedNames) {
188+
if (importedNames && !fromCore) {
191189
importedNames
192190
.filter((name) => {
193191
return name !== "any";

packages/typespec-ts/src/transform/transformSchemas.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {
1313
getSchemaForType,
1414
includeDerivedModel,
1515
getBodyType,
16-
trimUsage
16+
trimUsage,
17+
isAzureCoreErrorType
1718
} from "../utils/modelUtils.js";
1819
import { SdkContext } from "../utils/interfaces.js";
1920

@@ -61,12 +62,7 @@ export function transformSchemas(
6162
getGeneratedModels(bodyModel, SchemaContext.Input);
6263
}
6364
for (const resp of route.responses) {
64-
if (
65-
resp.type.kind === "Model" &&
66-
resp.type.name === "ErrorResponse" &&
67-
resp.type.namespace?.name === "Foundations" &&
68-
resp.type.namespace.namespace?.name === "Core"
69-
) {
65+
if (isAzureCoreErrorType(resp.type)) {
7066
continue;
7167
}
7268
for (const resps of resp.responses) {

0 commit comments

Comments
 (0)