@azure-tools/typespec-ts 0.30.1 → 0.31.0-alpha.20240723.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/src/contextManager.d.ts +4 -0
  3. package/dist/src/contextManager.d.ts.map +1 -1
  4. package/dist/src/contextManager.js.map +1 -1
  5. package/dist/src/framework/declaration.d.ts +9 -0
  6. package/dist/src/framework/declaration.d.ts.map +1 -0
  7. package/dist/src/framework/declaration.js +28 -0
  8. package/dist/src/framework/declaration.js.map +1 -0
  9. package/dist/src/framework/hooks/binder.d.ts +25 -0
  10. package/dist/src/framework/hooks/binder.d.ts.map +1 -0
  11. package/dist/src/framework/hooks/binder.js +168 -0
  12. package/dist/src/framework/hooks/binder.js.map +1 -0
  13. package/dist/src/framework/hooks/sdkTypes.d.ts +12 -0
  14. package/dist/src/framework/hooks/sdkTypes.d.ts.map +1 -0
  15. package/dist/src/framework/hooks/sdkTypes.js +67 -0
  16. package/dist/src/framework/hooks/sdkTypes.js.map +1 -0
  17. package/dist/src/framework/reference.d.ts +2 -0
  18. package/dist/src/framework/reference.d.ts.map +1 -0
  19. package/dist/src/framework/reference.js +8 -0
  20. package/dist/src/framework/reference.js.map +1 -0
  21. package/dist/src/framework/refkey.d.ts +7 -0
  22. package/dist/src/framework/refkey.d.ts.map +1 -0
  23. package/dist/src/framework/refkey.js +22 -0
  24. package/dist/src/framework/refkey.js.map +1 -0
  25. package/dist/src/framework/sample.d.ts +2 -0
  26. package/dist/src/framework/sample.d.ts.map +1 -0
  27. package/dist/src/framework/sample.js +71 -0
  28. package/dist/src/framework/sample.js.map +1 -0
  29. package/dist/src/framework/utils/tsmorph-helpers.d.ts +2 -0
  30. package/dist/src/framework/utils/tsmorph-helpers.d.ts.map +1 -0
  31. package/dist/src/framework/utils/tsmorph-helpers.js +2 -0
  32. package/dist/src/framework/utils/tsmorph-helpers.js.map +1 -0
  33. package/dist/src/index.d.ts.map +1 -1
  34. package/dist/src/index.js +7 -8
  35. package/dist/src/index.js.map +1 -1
  36. package/dist/src/lib.d.ts +10 -1
  37. package/dist/src/lib.d.ts.map +1 -1
  38. package/dist/src/lib.js +6 -0
  39. package/dist/src/lib.js.map +1 -1
  40. package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
  41. package/dist/src/modular/buildClassicalClient.js +6 -5
  42. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  43. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  44. package/dist/src/modular/buildClientContext.js +8 -4
  45. package/dist/src/modular/buildClientContext.js.map +1 -1
  46. package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
  47. package/dist/src/modular/buildCodeModel.js +22 -11
  48. package/dist/src/modular/buildCodeModel.js.map +1 -1
  49. package/dist/src/modular/buildOperations.d.ts +1 -2
  50. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  51. package/dist/src/modular/buildOperations.js +3 -9
  52. package/dist/src/modular/buildOperations.js.map +1 -1
  53. package/dist/src/modular/buildRootIndex.js +1 -1
  54. package/dist/src/modular/buildRootIndex.js.map +1 -1
  55. package/dist/src/modular/buildSerializeUtils.d.ts.map +1 -1
  56. package/dist/src/modular/buildSerializeUtils.js +2 -1
  57. package/dist/src/modular/buildSerializeUtils.js.map +1 -1
  58. package/dist/src/modular/helpers/clientHelpers.d.ts +4 -0
  59. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  60. package/dist/src/modular/helpers/clientHelpers.js +15 -1
  61. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  62. package/dist/src/modular/helpers/namingHelpers.d.ts +1 -0
  63. package/dist/src/modular/helpers/namingHelpers.d.ts.map +1 -1
  64. package/dist/src/modular/helpers/namingHelpers.js +3 -1
  65. package/dist/src/modular/helpers/namingHelpers.js.map +1 -1
  66. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  67. package/dist/src/modular/helpers/operationHelpers.js +60 -40
  68. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  69. package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
  70. package/dist/src/modular/helpers/typeHelpers.js +6 -1
  71. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  72. package/dist/src/modular/modularCodeModel.d.ts +2 -0
  73. package/dist/src/modular/modularCodeModel.d.ts.map +1 -1
  74. package/dist/src/transform/transformApiVersionInfo.d.ts.map +1 -1
  75. package/dist/src/transform/transformApiVersionInfo.js +3 -5
  76. package/dist/src/transform/transformApiVersionInfo.js.map +1 -1
  77. package/dist/src/transform/transformHelperFunctionDetails.d.ts.map +1 -1
  78. package/dist/src/transform/transformHelperFunctionDetails.js +7 -10
  79. package/dist/src/transform/transformHelperFunctionDetails.js.map +1 -1
  80. package/dist/src/transform/transformParameters.d.ts.map +1 -1
  81. package/dist/src/transform/transformParameters.js +5 -7
  82. package/dist/src/transform/transformParameters.js.map +1 -1
  83. package/dist/src/transform/transformPaths.d.ts.map +1 -1
  84. package/dist/src/transform/transformPaths.js +4 -6
  85. package/dist/src/transform/transformPaths.js.map +1 -1
  86. package/dist/src/transform/transformResponses.d.ts.map +1 -1
  87. package/dist/src/transform/transformResponses.js +70 -16
  88. package/dist/src/transform/transformResponses.js.map +1 -1
  89. package/dist/src/transform/transformSchemas.d.ts.map +1 -1
  90. package/dist/src/transform/transformSchemas.js +5 -6
  91. package/dist/src/transform/transformSchemas.js.map +1 -1
  92. package/dist/src/transform/transformTelemetryInfo.d.ts.map +1 -1
  93. package/dist/src/transform/transformTelemetryInfo.js +3 -6
  94. package/dist/src/transform/transformTelemetryInfo.js.map +1 -1
  95. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  96. package/dist/src/transform/transfromRLCOptions.js +5 -6
  97. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  98. package/dist/src/utils/modelUtils.d.ts +3 -3
  99. package/dist/src/utils/modelUtils.d.ts.map +1 -1
  100. package/dist/src/utils/modelUtils.js +42 -24
  101. package/dist/src/utils/modelUtils.js.map +1 -1
  102. package/dist/src/utils/operationUtil.d.ts +2 -2
  103. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  104. package/dist/src/utils/operationUtil.js +5 -7
  105. package/dist/src/utils/operationUtil.js.map +1 -1
  106. package/dist/tsconfig.tsbuildinfo +1 -1
  107. package/package.json +23 -23
  108. package/src/contextManager.ts +4 -0
  109. package/src/framework/declaration.ts +100 -0
  110. package/src/framework/hooks/binder.ts +259 -0
  111. package/src/framework/hooks/sdkTypes.ts +101 -0
  112. package/src/framework/reference.ts +9 -0
  113. package/src/framework/refkey.ts +28 -0
  114. package/src/framework/sample.ts +92 -0
  115. package/src/framework/utils/tsmorph-helpers.ts +0 -0
  116. package/src/index.ts +8 -10
  117. package/src/lib.ts +6 -0
  118. package/src/modular/buildClassicalClient.ts +11 -4
  119. package/src/modular/buildClientContext.ts +11 -5
  120. package/src/modular/buildCodeModel.ts +25 -21
  121. package/src/modular/buildOperations.ts +13 -41
  122. package/src/modular/buildRootIndex.ts +1 -1
  123. package/src/modular/buildSerializeUtils.ts +2 -1
  124. package/src/modular/helpers/clientHelpers.ts +25 -1
  125. package/src/modular/helpers/namingHelpers.ts +4 -1
  126. package/src/modular/helpers/operationHelpers.ts +86 -45
  127. package/src/modular/helpers/typeHelpers.ts +6 -1
  128. package/src/modular/modularCodeModel.ts +2 -0
  129. package/src/transform/transformApiVersionInfo.ts +3 -6
  130. package/src/transform/transformHelperFunctionDetails.ts +9 -9
  131. package/src/transform/transformParameters.ts +5 -6
  132. package/src/transform/transformPaths.ts +5 -9
  133. package/src/transform/transformResponses.ts +92 -19
  134. package/src/transform/transformSchemas.ts +6 -5
  135. package/src/transform/transformTelemetryInfo.ts +3 -5
  136. package/src/transform/transfromRLCOptions.ts +5 -10
  137. package/src/utils/modelUtils.ts +49 -39
  138. package/src/utils/operationUtil.ts +6 -12
  139. package/dist/src/modular/serialization/collectionUtils.d.ts +0 -3
  140. package/dist/src/modular/serialization/collectionUtils.d.ts.map +0 -1
  141. package/dist/src/modular/serialization/collectionUtils.js +0 -17
  142. package/dist/src/modular/serialization/collectionUtils.js.map +0 -1
  143. package/dist/src/modular/serialization/index.d.ts +0 -5
  144. package/dist/src/modular/serialization/index.d.ts.map +0 -1
  145. package/dist/src/modular/serialization/index.js +0 -155
  146. package/dist/src/modular/serialization/index.js.map +0 -1
  147. package/dist/src/modular/serialization/operationHelpers.d.ts +0 -37
  148. package/dist/src/modular/serialization/operationHelpers.d.ts.map +0 -1
  149. package/dist/src/modular/serialization/operationHelpers.js +0 -457
  150. package/dist/src/modular/serialization/operationHelpers.js.map +0 -1
  151. package/dist/src/modular/serialization/serializeArray.d.ts +0 -5
  152. package/dist/src/modular/serialization/serializeArray.d.ts.map +0 -1
  153. package/dist/src/modular/serialization/serializeArray.js +0 -33
  154. package/dist/src/modular/serialization/serializeArray.js.map +0 -1
  155. package/dist/src/modular/serialization/serializeDateTime.d.ts +0 -4
  156. package/dist/src/modular/serialization/serializeDateTime.d.ts.map +0 -1
  157. package/dist/src/modular/serialization/serializeDateTime.js +0 -19
  158. package/dist/src/modular/serialization/serializeDateTime.js.map +0 -1
  159. package/dist/src/modular/serialization/serializeHeaders.d.ts +0 -7
  160. package/dist/src/modular/serialization/serializeHeaders.d.ts.map +0 -1
  161. package/dist/src/modular/serialization/serializeHeaders.js +0 -44
  162. package/dist/src/modular/serialization/serializeHeaders.js.map +0 -1
  163. package/dist/src/modular/serialization/serializers.d.ts +0 -17
  164. package/dist/src/modular/serialization/serializers.d.ts.map +0 -1
  165. package/dist/src/modular/serialization/serializers.js +0 -175
  166. package/dist/src/modular/serialization/serializers.js.map +0 -1
  167. package/dist/src/modular/serialization/util.d.ts +0 -27
  168. package/dist/src/modular/serialization/util.d.ts.map +0 -1
  169. package/dist/src/modular/serialization/util.js +0 -115
  170. package/dist/src/modular/serialization/util.js.map +0 -1
  171. package/dist/src/reify/index.d.ts +0 -12
  172. package/dist/src/reify/index.d.ts.map +0 -1
  173. package/dist/src/reify/index.js +0 -22
  174. package/dist/src/reify/index.js.map +0 -1
  175. package/src/modular/serialization/collectionUtils.ts +0 -20
  176. package/src/modular/serialization/index.ts +0 -267
  177. package/src/modular/serialization/operationHelpers.ts +0 -659
  178. package/src/modular/serialization/serializeArray.ts +0 -51
  179. package/src/modular/serialization/serializeDateTime.ts +0 -22
  180. package/src/modular/serialization/serializeHeaders.ts +0 -64
  181. package/src/modular/serialization/serializers.ts +0 -304
  182. package/src/modular/serialization/util.ts +0 -171
  183. package/src/modular/static/karma.conf.cjs +0 -120
  184. package/src/reify/index.ts +0 -41
@@ -37,6 +37,7 @@ import {
37
37
  Operation,
38
38
  Parameter,
39
39
  Property,
40
+ Response,
40
41
  Type
41
42
  } from "../modularCodeModel.js";
42
43
  import {
@@ -46,30 +47,55 @@ import {
46
47
  import { getClassicalLayerPrefix, getOperationName } from "./namingHelpers.js";
47
48
  import { buildType, isTypeNullable } from "./typeHelpers.js";
48
49
 
49
- function getRLCResponseType(rlcResponse?: OperationResponse) {
50
+ function getRLCResponseTypes(rlcResponse?: OperationResponse) {
50
51
  if (!rlcResponse?.responses) {
51
52
  return;
52
53
  }
53
54
  return rlcResponse?.responses
54
- .map((resp) => {
55
- const baseResponseName = getResponseBaseName(
56
- rlcResponse.operationGroup,
57
- rlcResponse.operationName,
58
- resp.statusCode
59
- );
60
- // Get the information to build the Response Interface
61
- return resp.predefinedName ?? getResponseTypeName(baseResponseName);
62
- })
55
+ .map(
56
+ (resp) =>
57
+ resp.predefinedName ?? getRLCResponseType(resp.statusCode, rlcResponse)
58
+ )
63
59
  .join(" | ");
64
60
  }
65
61
 
66
- function getRLCLroLogicalResponse(rlcResponse?: OperationResponse) {
67
- const logicalResponse = (rlcResponse?.responses ?? []).filter(
68
- (r) => r.predefinedName && r.predefinedName.endsWith(`LogicalResponse`)
62
+ function getRLCResponseType(
63
+ statusCode: string,
64
+ operationInfo?: OperationResponse
65
+ ) {
66
+ if (!operationInfo) {
67
+ return;
68
+ }
69
+ const baseResponseName = getResponseBaseName(
70
+ operationInfo.operationGroup,
71
+ operationInfo.operationName,
72
+ statusCode
73
+ );
74
+ // Get the information to build the Response Interface
75
+ return getResponseTypeName(baseResponseName);
76
+ }
77
+
78
+ function getNarrowedRLCResponse(
79
+ response: Response,
80
+ rlcResponse?: OperationResponse
81
+ ): string | undefined {
82
+ if (!rlcResponse) {
83
+ return;
84
+ }
85
+ const statusCode = response.statusCodes;
86
+ const names = getRLCResponseTypes(rlcResponse)?.split(" | ");
87
+ const lroResponse = names?.filter((n) => n.endsWith(`LogicalResponse`));
88
+ const normalResponse = names?.filter(
89
+ (n) => n === getRLCResponseType(`${statusCode}`, rlcResponse)
90
+ );
91
+ return (
92
+ // if the response is a LRO response, narrow to the lro logical response
93
+ lroResponse?.at(0) ??
94
+ // if the default response is a superset of one of other responses, narrow to the normal response
95
+ (rlcResponse.isDefaultSupersetOfOthers
96
+ ? normalResponse?.at(0) ?? "any"
97
+ : undefined)
69
98
  );
70
- return logicalResponse.length > 0
71
- ? logicalResponse[0]!.predefinedName!
72
- : "any";
73
99
  }
74
100
 
75
101
  export function getSendPrivateFunction(
@@ -80,7 +106,7 @@ export function getSendPrivateFunction(
80
106
  ): OptionalKind<FunctionDeclarationStructure> {
81
107
  const parameters = getOperationSignatureParameters(operation, clientType);
82
108
  const { name } = getOperationName(operation);
83
- const returnType = `StreamableMethod<${getRLCResponseType(
109
+ const returnType = `StreamableMethod<${getRLCResponseTypes(
84
110
  operation.rlcResponse
85
111
  )}>`;
86
112
 
@@ -125,7 +151,7 @@ export function getDeserializePrivateFunction(
125
151
  const parameters: OptionalKind<ParameterDeclarationStructure>[] = [
126
152
  {
127
153
  name: "result",
128
- type: getRLCResponseType(operation.rlcResponse)
154
+ type: getRLCResponseTypes(operation.rlcResponse)
129
155
  }
130
156
  ];
131
157
  // TODO: Support LRO + paging operation
@@ -183,31 +209,31 @@ export function getDeserializePrivateFunction(
183
209
  }
184
210
  }
185
211
 
186
- let deserializedType = isLroOnly
212
+ const deserializedType = isLroOnly
187
213
  ? operation?.lroMetadata?.finalResult
188
214
  : response.type;
189
- let hasLroSubPath = operation?.lroMetadata?.finalResultPath !== undefined;
190
- let deserializedRoot = hasLroSubPath
191
- ? `result.body.${operation?.lroMetadata?.finalResultPath}`
192
- : "result.body";
193
- // TODO: Hard-coded for LRO PATCH case for now
194
- // https://github.com/Azure/autorest.typescript/issues/2314
195
- if (isLroOnly && operation.method.toLowerCase() === "patch") {
196
- deserializedType = response.type;
197
- hasLroSubPath = false;
198
- deserializedRoot = "result.body";
215
+ const hasLroSubPath = operation?.lroMetadata?.finalResultPath !== undefined;
216
+ // Narrow down the rlc response type to deserialized one
217
+ const isNarrowedResponse = getNarrowedRLCResponse(
218
+ response,
219
+ operation.rlcResponse
220
+ );
221
+ let deserializePrefix = "result.body";
222
+ if (isNarrowedResponse) {
223
+ statements.push(`const res = result as unknown as ${isNarrowedResponse};`);
224
+ deserializePrefix = "res.body";
199
225
  }
200
- if (isLroOnly) {
201
- const lroLogicalResponse = getRLCLroLogicalResponse(operation.rlcResponse);
202
- statements.push(`result = result as ${lroLogicalResponse};`);
203
- if (hasLroSubPath) {
204
- statements.push(
205
- `if(${deserializedRoot.split(".").join("?.")} === undefined) {
206
- throw createRestError(\`Expected a result in the response at position "${deserializedRoot}"\`, result);
207
- }
208
- `
209
- );
210
- }
226
+
227
+ const deserializedRoot = hasLroSubPath
228
+ ? `${deserializePrefix}.${operation?.lroMetadata?.finalResultPath}`
229
+ : `${deserializePrefix}`;
230
+ if (isLroOnly && hasLroSubPath) {
231
+ statements.push(
232
+ `if(${deserializedRoot.split(".").join("?.")} === undefined) {
233
+ throw createRestError(\`Expected a result in the response at position "${deserializedRoot}"\`, result);
234
+ }
235
+ `
236
+ );
211
237
  }
212
238
 
213
239
  const allParents = deserializedType ? getAllAncestors(deserializedType) : [];
@@ -222,7 +248,7 @@ export function getDeserializePrivateFunction(
222
248
  response.isBinaryPayload
223
249
  ) {
224
250
  // TODO: Fix this any cast when implementing handling dict.
225
- statements.push(`return result.body as any`);
251
+ statements.push(`return ${deserializedRoot} as any`);
226
252
  } else if (
227
253
  deserializedType &&
228
254
  properties.length > 0 &&
@@ -658,8 +684,15 @@ function buildBodyParameter(
658
684
  directAssignment === true
659
685
  ? bodyParts.join(", ")
660
686
  : `{ ${bodyParts.join(", ")} }`;
687
+ let bodyElementStatement = "";
688
+ if (
689
+ isTypeNullable(bodyParameter.type.elementType) ||
690
+ bodyParameter.type.elementType.optional
691
+ ) {
692
+ bodyElementStatement = `!p ? p : `;
693
+ }
661
694
  return `\nbody: (${bodyParameter.clientName} ?? []).map((p) => {
662
- return ${mapBody};
695
+ return ${bodyElementStatement}${mapBody};
663
696
  }),`;
664
697
  }
665
698
  return `\nbody: ${bodyParameter.clientName},`;
@@ -1206,12 +1239,16 @@ export function deserializeResponseValue(
1206
1239
  : `${requiredOrNullablePrefix} ? ${restValue} : ${restValue}`;
1207
1240
  if (type.elementType?.type === "model") {
1208
1241
  if (!type.elementType.aliasType) {
1209
- return `${prefix}.map(p => ({${getResponseMapping(
1242
+ const elementNullOrUndefinedPrefix =
1243
+ isTypeNullable(type.elementType) || type.elementType.optional
1244
+ ? "!p ? p :"
1245
+ : "";
1246
+ return `${prefix}.map(p => { return ${elementNullOrUndefinedPrefix}{${getResponseMapping(
1210
1247
  type.elementType,
1211
1248
  "p",
1212
1249
  runtimeImports,
1213
1250
  [...typeStack, type.elementType]
1214
- )}}))`;
1251
+ )}}})`;
1215
1252
  } else if (isPolymorphicUnion(type.elementType)) {
1216
1253
  let nullOrUndefinedPrefix = "";
1217
1254
  if (isTypeNullable(type.elementType)) {
@@ -1328,6 +1365,10 @@ export function serializeRequestValue(
1328
1365
  ? `${clientValue}`
1329
1366
  : `${requiredOrNullablePrefix}? ${clientValue}: ${clientValue}`;
1330
1367
  if (type.elementType?.type === "model" && !type.elementType.aliasType) {
1368
+ const elementNullOrUndefinedPrefix =
1369
+ isTypeNullable(type.elementType) || type.elementType.optional
1370
+ ? "!p ? p :"
1371
+ : "";
1331
1372
  if (!type.elementType.name) {
1332
1373
  // If it is an anonymous model we need to serialize inline
1333
1374
  const { propertiesStr } = getRequestModelMapping(
@@ -1337,7 +1378,7 @@ export function serializeRequestValue(
1337
1378
  [...typeStack, type.elementType]
1338
1379
  );
1339
1380
 
1340
- return `${prefix}.map(p => ({${propertiesStr}}))`;
1381
+ return `${prefix}.map(p => { return ${elementNullOrUndefinedPrefix}{${propertiesStr}}})`;
1341
1382
  } else {
1342
1383
  // When it is not anonymous we can hand it off to the serializer function
1343
1384
  return `${prefix}.map(${toCamelCase(
@@ -246,8 +246,13 @@ function handleDictType(type: Type): TypeMetadata {
246
246
  }
247
247
  const elementType = getType(type.elementType, type.elementType.format);
248
248
  const elementName = elementType.name;
249
+ const name = handleNullableTypeName({
250
+ name: `Record<string, ${elementName}>`,
251
+ nullable: isTypeNullable(type)
252
+ });
249
253
  return {
250
- name: `Record<string, ${elementName}>`
254
+ name,
255
+ nullable: isTypeNullable(type)
251
256
  };
252
257
  }
253
258
 
@@ -120,6 +120,8 @@ export interface Type {
120
120
  isPolymorphicBaseModel?: boolean;
121
121
  tcgcType?: SdkType;
122
122
  __raw?: TypespecType;
123
+ nullable?: boolean;
124
+ optional?: boolean;
123
125
  }
124
126
 
125
127
  export interface Client {
@@ -7,13 +7,12 @@ import {
7
7
  UrlInfo
8
8
  } from "@azure-tools/rlc-common";
9
9
  import {
10
+ getHttpOperationWithCache,
10
11
  isApiVersion,
11
12
  listOperationGroups,
12
13
  listOperationsInOperationGroup,
13
14
  SdkClient
14
15
  } from "@azure-tools/typespec-client-generator-core";
15
- import { ignoreDiagnostics } from "@typespec/compiler";
16
- import { getHttpOperation } from "@typespec/http";
17
16
  import { SdkContext } from "../utils/interfaces.js";
18
17
  import {
19
18
  getDefaultApiVersionString,
@@ -71,9 +70,7 @@ export function getOperationApiVersion(
71
70
  let hasApiVersionInOperation = true;
72
71
  for (const clientOp of clientOperations) {
73
72
  hasApiVersionInOperation = false;
74
- const route = ignoreDiagnostics(
75
- getHttpOperation(dpgContext.program, clientOp)
76
- );
73
+ const route = getHttpOperationWithCache(dpgContext, clientOp);
77
74
  // ignore overload base operation
78
75
  if (route.overloads && route.overloads?.length > 0) {
79
76
  continue;
@@ -113,7 +110,7 @@ export function getOperationApiVersion(
113
110
  );
114
111
  for (const op of operations) {
115
112
  hasApiVersionInOperation = false;
116
- const route = ignoreDiagnostics(getHttpOperation(dpgContext.program, op));
113
+ const route = getHttpOperationWithCache(dpgContext, op);
117
114
  // ignore overload base operation
118
115
  if (route.overloads && route.overloads?.length > 0) {
119
116
  continue;
@@ -1,11 +1,12 @@
1
1
  import { HelperFunctionDetails, PackageFlavor } from "@azure-tools/rlc-common";
2
2
  import {
3
+ getHttpOperationWithCache,
3
4
  listOperationGroups,
4
5
  listOperationsInOperationGroup,
5
6
  SdkClient
6
7
  } from "@azure-tools/typespec-client-generator-core";
7
- import { ignoreDiagnostics, Model, Program, Type } from "@typespec/compiler";
8
- import { getHttpOperation, HttpOperation } from "@typespec/http";
8
+ import { Model, Program, Type } from "@typespec/compiler";
9
+ import { HttpOperation } from "@typespec/http";
9
10
  import { SdkContext } from "../utils/interfaces.js";
10
11
  import {
11
12
  extractPagedMetadataNested,
@@ -48,7 +49,7 @@ export function transformHelperFunctionDetails(
48
49
  const nextLinks = new Set<string>();
49
50
  const clientOperations = listOperationsInOperationGroup(dpgContext, client);
50
51
  for (const clientOp of clientOperations) {
51
- const route = ignoreDiagnostics(getHttpOperation(program, clientOp));
52
+ const route = getHttpOperationWithCache(dpgContext, clientOp);
52
53
  // ignore overload base operation
53
54
  if (route.overloads && route.overloads?.length > 0) {
54
55
  continue;
@@ -67,7 +68,7 @@ export function transformHelperFunctionDetails(
67
68
  operationGroup
68
69
  );
69
70
  for (const op of operations) {
70
- const route = ignoreDiagnostics(getHttpOperation(program, op));
71
+ const route = getHttpOperationWithCache(dpgContext, op);
71
72
  // ignore overload base operation
72
73
  if (route.overloads && route.overloads?.length > 0) {
73
74
  continue;
@@ -118,7 +119,7 @@ function extractPageDetailFromCore(client: SdkClient, dpgContext: SdkContext) {
118
119
  itemNames.add("value");
119
120
  const clientOperations = listOperationsInOperationGroup(dpgContext, client);
120
121
  for (const clientOp of clientOperations) {
121
- const route = ignoreDiagnostics(getHttpOperation(program, clientOp));
122
+ const route = getHttpOperationWithCache(dpgContext, clientOp);
122
123
  // ignore overload base operation
123
124
  if (route.overloads && route.overloads?.length > 0) {
124
125
  continue;
@@ -132,7 +133,7 @@ function extractPageDetailFromCore(client: SdkClient, dpgContext: SdkContext) {
132
133
  operationGroup
133
134
  );
134
135
  for (const op of operations) {
135
- const route = ignoreDiagnostics(getHttpOperation(program, op));
136
+ const route = getHttpOperationWithCache(dpgContext, op);
136
137
  // ignore overload base operation
137
138
  if (route.overloads && route.overloads?.length > 0) {
138
139
  continue;
@@ -175,7 +176,6 @@ function extractSpecialSerializeInfo(
175
176
  client: SdkClient,
176
177
  dpgContext: SdkContext
177
178
  ) {
178
- const program = dpgContext.program;
179
179
  let hasMultiCollection = false;
180
180
  let hasPipeCollection = false;
181
181
  let hasTsvCollection = false;
@@ -183,7 +183,7 @@ function extractSpecialSerializeInfo(
183
183
  let hasCsvCollection = false;
184
184
  const clientOperations = listOperationsInOperationGroup(dpgContext, client);
185
185
  for (const clientOp of clientOperations) {
186
- const route = ignoreDiagnostics(getHttpOperation(program, clientOp));
186
+ const route = getHttpOperationWithCache(dpgContext, clientOp);
187
187
  route.parameters.parameters.forEach((parameter) => {
188
188
  const serializeInfo = getSpecialSerializeInfo(
189
189
  parameter.type,
@@ -213,7 +213,7 @@ function extractSpecialSerializeInfo(
213
213
  operationGroup
214
214
  );
215
215
  for (const op of operations) {
216
- const route = ignoreDiagnostics(getHttpOperation(program, op));
216
+ const route = getHttpOperationWithCache(dpgContext, op);
217
217
  route.parameters.parameters.forEach((parameter) => {
218
218
  const serializeInfo = getSpecialSerializeInfo(
219
219
  parameter.type,
@@ -11,9 +11,8 @@ import {
11
11
  Schema,
12
12
  SchemaContext
13
13
  } from "@azure-tools/rlc-common";
14
- import { ignoreDiagnostics, isVoidType, Type } from "@typespec/compiler";
14
+ import { isVoidType, Type } from "@typespec/compiler";
15
15
  import {
16
- getHttpOperation,
17
16
  HttpOperation,
18
17
  HttpOperationParameter,
19
18
  HttpOperationParameters
@@ -28,6 +27,7 @@ import {
28
27
  } from "../utils/modelUtils.js";
29
28
 
30
29
  import {
30
+ getHttpOperationWithCache,
31
31
  isApiVersion,
32
32
  listOperationGroups,
33
33
  listOperationsInOperationGroup,
@@ -52,12 +52,11 @@ export function transformToParameterTypes(
52
52
  importDetails: Imports,
53
53
  apiVersionInfo?: ApiVersionInfo
54
54
  ): OperationParameter[] {
55
- const program = dpgContext.program;
56
55
  const rlcParameters: OperationParameter[] = [];
57
56
  const outputImportedSet = new Set<string>();
58
57
  const clientOperations = listOperationsInOperationGroup(dpgContext, client);
59
58
  for (const clientOp of clientOperations) {
60
- const route = ignoreDiagnostics(getHttpOperation(program, clientOp));
59
+ const route = getHttpOperationWithCache(dpgContext, clientOp);
61
60
  // ignore overload base operation
62
61
  if (route.overloads && route.overloads?.length > 0) {
63
62
  continue;
@@ -71,7 +70,7 @@ export function transformToParameterTypes(
71
70
  operationGroup
72
71
  );
73
72
  for (const op of operations) {
74
- const route = ignoreDiagnostics(getHttpOperation(program, op));
73
+ const route = getHttpOperationWithCache(dpgContext, op);
75
74
  // ignore overload base operation
76
75
  if (route.overloads && route.overloads?.length > 0) {
77
76
  continue;
@@ -106,7 +105,7 @@ export function transformToParameterTypes(
106
105
  outputImportedSet
107
106
  );
108
107
  // transform body
109
- const bodyType = getBodyType(program, route);
108
+ const bodyType = getBodyType(route);
110
109
  let bodyParameter = undefined;
111
110
  if (bodyType) {
112
111
  bodyParameter = transformBodyParameters(
@@ -11,17 +11,14 @@ import {
11
11
  SchemaContext
12
12
  } from "@azure-tools/rlc-common";
13
13
  import {
14
+ getHttpOperationWithCache,
14
15
  isApiVersion,
15
16
  listOperationGroups,
16
17
  listOperationsInOperationGroup,
17
18
  SdkClient
18
19
  } from "@azure-tools/typespec-client-generator-core";
19
- import { getDoc, ignoreDiagnostics } from "@typespec/compiler";
20
- import {
21
- getHttpOperation,
22
- HttpOperation,
23
- HttpOperationParameters
24
- } from "@typespec/http";
20
+ import { getDoc } from "@typespec/compiler";
21
+ import { HttpOperation, HttpOperationParameters } from "@typespec/http";
25
22
  import { SdkContext } from "../utils/interfaces.js";
26
23
  import {
27
24
  getImportedModelName,
@@ -44,12 +41,11 @@ export function transformPaths(
44
41
  dpgContext: SdkContext,
45
42
  importDetails: Imports
46
43
  ): Paths {
47
- const program = dpgContext.program;
48
44
  const pathParamsImportedSet = new Set<string>();
49
45
  const paths: Paths = {};
50
46
  const clientOperations = listOperationsInOperationGroup(dpgContext, client);
51
47
  for (const clientOp of clientOperations) {
52
- const route = ignoreDiagnostics(getHttpOperation(program, clientOp));
48
+ const route = getHttpOperationWithCache(dpgContext, clientOp);
53
49
  // ignore overload base operation
54
50
  if (route.overloads && route.overloads?.length > 0) {
55
51
  continue;
@@ -63,7 +59,7 @@ export function transformPaths(
63
59
  operationGroup
64
60
  );
65
61
  for (const op of operations) {
66
- const route = ignoreDiagnostics(getHttpOperation(program, op));
62
+ const route = getHttpOperationWithCache(dpgContext, op);
67
63
  // ignore overload base operation
68
64
  if (route.overloads && route.overloads?.length > 0) {
69
65
  continue;
@@ -4,6 +4,8 @@
4
4
  import {
5
5
  getLroLogicalResponseName,
6
6
  Imports,
7
+ isObjectSchema,
8
+ ObjectSchema,
7
9
  OperationResponse,
8
10
  ResponseHeaderSchema,
9
11
  ResponseMetadata,
@@ -11,16 +13,13 @@ import {
11
13
  SchemaContext
12
14
  } from "@azure-tools/rlc-common";
13
15
  import {
16
+ getHttpOperationWithCache,
14
17
  listOperationGroups,
15
18
  listOperationsInOperationGroup,
16
19
  SdkClient
17
20
  } from "@azure-tools/typespec-client-generator-core";
18
- import { getDoc, ignoreDiagnostics, isVoidType } from "@typespec/compiler";
19
- import {
20
- getHttpOperation,
21
- HttpOperation,
22
- HttpOperationResponse
23
- } from "@typespec/http";
21
+ import { getDoc, isVoidType, NoTarget } from "@typespec/compiler";
22
+ import { HttpOperation, HttpOperationResponse } from "@typespec/http";
24
23
  import { SdkContext } from "../utils/interfaces.js";
25
24
  import {
26
25
  getBinaryType,
@@ -36,18 +35,18 @@ import {
36
35
  isBinaryPayload,
37
36
  sortedOperationResponses
38
37
  } from "../utils/operationUtil.js";
38
+ import { reportDiagnostic } from "../lib.js";
39
39
 
40
40
  export function transformToResponseTypes(
41
41
  client: SdkClient,
42
42
  dpgContext: SdkContext,
43
43
  importDetails: Imports
44
44
  ): OperationResponse[] {
45
- const program = dpgContext.program;
46
45
  const rlcResponses: OperationResponse[] = [];
47
46
  const inputImportedSet = new Set<string>();
48
47
  const clientOperations = listOperationsInOperationGroup(dpgContext, client);
49
48
  for (const clientOp of clientOperations) {
50
- const route = ignoreDiagnostics(getHttpOperation(program, clientOp));
49
+ const route = getHttpOperationWithCache(dpgContext, clientOp);
51
50
  // ignore overload base operation
52
51
  if (route.overloads && route.overloads?.length > 0) {
53
52
  continue;
@@ -61,7 +60,7 @@ export function transformToResponseTypes(
61
60
  operationGroup
62
61
  );
63
62
  for (const op of operations) {
64
- const route = ignoreDiagnostics(getHttpOperation(program, op));
63
+ const route = getHttpOperationWithCache(dpgContext, op);
65
64
  // ignore overload base operation
66
65
  if (route.overloads && route.overloads?.length > 0) {
67
66
  continue;
@@ -77,8 +76,11 @@ export function transformToResponseTypes(
77
76
  operationGroup: getOperationGroupName(dpgContext, route),
78
77
  operationName: getOperationName(dpgContext, route.operation),
79
78
  path: route.path,
79
+ isDefaultSupersetOfOthers: false,
80
80
  responses: []
81
81
  };
82
+ const defaultSchemas: Schema[] = [],
83
+ nonDefaultSchemas: Schema[] = [];
82
84
  for (const resp of sortedOperationResponses(route.responses)) {
83
85
  const statusCode = getOperationStatuscode(resp);
84
86
  const rlcResponseUnit: ResponseMetadata = {
@@ -88,12 +90,21 @@ export function transformToResponseTypes(
88
90
  // transform header
89
91
  const headers = transformHeaders(dpgContext, resp, inputImportedSet);
90
92
  // transform body
91
- const body = transformBody(dpgContext, resp, inputImportedSet);
93
+ const [body, schemas] = transformBody(
94
+ dpgContext,
95
+ resp,
96
+ inputImportedSet
97
+ ) ?? [undefined, []];
92
98
  rlcOperationUnit.responses.push({
93
99
  ...rlcResponseUnit,
94
100
  headers,
95
101
  body
96
102
  });
103
+ if (statusCode === "default") {
104
+ defaultSchemas.push(...schemas);
105
+ } else {
106
+ nonDefaultSchemas.push(...schemas);
107
+ }
97
108
  }
98
109
  const lroLogicalResponse = transformLroLogicalResponse(
99
110
  dpgContext,
@@ -104,15 +115,72 @@ export function transformToResponseTypes(
104
115
  if (lroLogicalResponse) {
105
116
  rlcOperationUnit.responses.push(lroLogicalResponse);
106
117
  }
118
+ rlcOperationUnit.isDefaultSupersetOfOthers =
119
+ transformIsDefaultSupersetOfOthers(
120
+ dpgContext,
121
+ defaultSchemas,
122
+ nonDefaultSchemas,
123
+ getOperationName(dpgContext, route.operation)
124
+ );
107
125
  rlcResponses.push(rlcOperationUnit);
108
126
  }
109
127
  return rlcResponses;
110
128
  }
111
129
 
130
+ function transformIsDefaultSupersetOfOthers(
131
+ dpgContext: SdkContext,
132
+ defaultSchemas: Schema[],
133
+ nonDefaultSchemas: Schema[],
134
+ operationName: string
135
+ ): boolean {
136
+ if (defaultSchemas.length !== 1 || nonDefaultSchemas.length === 0) {
137
+ return false;
138
+ }
139
+ if (!isObjectSchema(defaultSchemas[0]!)) {
140
+ reportDiagnostic(dpgContext.program, {
141
+ code: "default-response-body-type",
142
+ format: {
143
+ operationName
144
+ },
145
+ target: NoTarget
146
+ });
147
+ return false;
148
+ }
149
+ const [typeName, properties] = getNameAndPropertyMap(defaultSchemas[0]!);
150
+ for (const schema of nonDefaultSchemas) {
151
+ if (!isObjectSchema(schema)) {
152
+ return false;
153
+ }
154
+ const [nonDefaultTypeName, nonDefaultProperties] =
155
+ getNameAndPropertyMap(schema);
156
+ if (typeName === nonDefaultTypeName) {
157
+ return true;
158
+ }
159
+ // check if any properties in default schema is existing in non-default schema
160
+ for (const [propName, propTypeName] of properties) {
161
+ if (propTypeName === nonDefaultProperties.get(propName)) {
162
+ return true;
163
+ }
164
+ }
165
+ }
166
+
167
+ return false;
168
+ }
169
+
170
+ function getNameAndPropertyMap(
171
+ schema: ObjectSchema
172
+ ): [string, Map<string, string>] {
173
+ const map = new Map<string, string>();
174
+ for (const [key, value] of Object.entries(schema.properties!)) {
175
+ map.set(key, getTypeName(value));
176
+ }
177
+ return [getTypeName(schema), map];
178
+ }
179
+
112
180
  /**
113
181
  * Return undefined if no valid header param
114
182
  * @param response response detail
115
- * @returns rlc header shcema
183
+ * @returns rlc header schema
116
184
  */
117
185
  function transformHeaders(
118
186
  dpgContext: SdkContext,
@@ -166,15 +234,16 @@ function transformBody(
166
234
  dpgContext: SdkContext,
167
235
  response: HttpOperationResponse,
168
236
  importedModels: Set<string>
169
- ) {
237
+ ): [Schema, Schema[]] | undefined {
170
238
  if (!response.responses.length) {
171
239
  return;
172
240
  }
173
- // Currently RLC reponse only have one header and body defined
241
+ // Currently RLC response only have one header and body defined
174
242
  // So we'll union all body shapes together with "|"
175
243
  const typeSet = new Set<string>();
176
244
  const descriptions = new Set<string>();
177
245
  let fromCore = false;
246
+ const schemas = [];
178
247
  for (const data of response.responses) {
179
248
  const body = data?.body;
180
249
  if (!body || isVoidType(body.type)) {
@@ -202,18 +271,22 @@ function transformBody(
202
271
  .forEach(importedModels.add, importedModels);
203
272
  }
204
273
  typeSet.add(bodyType);
274
+ schemas.push(bodySchema);
205
275
  }
206
276
 
207
277
  if (!typeSet.size) {
208
278
  return;
209
279
  }
210
280
 
211
- return {
212
- name: "body",
213
- type: [...typeSet].join("|"),
214
- description: [...descriptions].join("\n\n"),
215
- fromCore
216
- };
281
+ return [
282
+ {
283
+ name: "body",
284
+ type: [...typeSet].join("|"),
285
+ description: [...descriptions].join("\n\n"),
286
+ fromCore
287
+ },
288
+ schemas
289
+ ];
217
290
  }
218
291
 
219
292
  function transformLroLogicalResponse(