@azure-tools/typespec-ts 0.31.0 → 0.32.0

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 (169) hide show
  1. package/CHANGELOG.md +25 -7
  2. package/README.md +8 -0
  3. package/dist/src/contextManager.d.ts +2 -0
  4. package/dist/src/contextManager.d.ts.map +1 -1
  5. package/dist/src/contextManager.js.map +1 -1
  6. package/dist/src/framework/dependency.d.ts +69 -0
  7. package/dist/src/framework/dependency.d.ts.map +1 -0
  8. package/dist/src/framework/dependency.js +2 -0
  9. package/dist/src/framework/dependency.js.map +1 -0
  10. package/dist/src/framework/hooks/binder.d.ts +8 -2
  11. package/dist/src/framework/hooks/binder.d.ts.map +1 -1
  12. package/dist/src/framework/hooks/binder.js +107 -20
  13. package/dist/src/framework/hooks/binder.js.map +1 -1
  14. package/dist/src/framework/hooks/useDependencies.d.ts +4 -0
  15. package/dist/src/framework/hooks/useDependencies.d.ts.map +1 -0
  16. package/dist/src/framework/hooks/useDependencies.js +13 -0
  17. package/dist/src/framework/hooks/useDependencies.js.map +1 -0
  18. package/dist/src/framework/load-static-helpers.d.ts +16 -0
  19. package/dist/src/framework/load-static-helpers.d.ts.map +1 -0
  20. package/dist/src/framework/load-static-helpers.js +93 -0
  21. package/dist/src/framework/load-static-helpers.js.map +1 -0
  22. package/dist/src/framework/reference.d.ts +1 -1
  23. package/dist/src/framework/reference.d.ts.map +1 -1
  24. package/dist/src/framework/reference.js +16 -2
  25. package/dist/src/framework/reference.js.map +1 -1
  26. package/dist/src/framework/sample.js +1 -1
  27. package/dist/src/framework/sample.js.map +1 -1
  28. package/dist/src/index.d.ts +1 -1
  29. package/dist/src/index.d.ts.map +1 -1
  30. package/dist/src/index.js +113 -79
  31. package/dist/src/index.js.map +1 -1
  32. package/dist/src/lib.d.ts +10 -1
  33. package/dist/src/lib.d.ts.map +1 -1
  34. package/dist/src/lib.js +8 -1
  35. package/dist/src/lib.js.map +1 -1
  36. package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
  37. package/dist/src/modular/buildClassicalClient.js +12 -9
  38. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  39. package/dist/src/modular/buildClassicalOperationGroups.d.ts.map +1 -1
  40. package/dist/src/modular/buildClassicalOperationGroups.js +1 -11
  41. package/dist/src/modular/buildClassicalOperationGroups.js.map +1 -1
  42. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  43. package/dist/src/modular/buildClientContext.js +73 -52
  44. package/dist/src/modular/buildClientContext.js.map +1 -1
  45. package/dist/src/modular/buildCodeModel.d.ts +1 -1
  46. package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
  47. package/dist/src/modular/buildCodeModel.js +36 -62
  48. package/dist/src/modular/buildCodeModel.js.map +1 -1
  49. package/dist/src/modular/buildHelperSerializers.d.ts.map +1 -1
  50. package/dist/src/modular/buildHelperSerializers.js.map +1 -1
  51. package/dist/src/modular/buildOperations.d.ts +1 -3
  52. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  53. package/dist/src/modular/buildOperations.js +9 -69
  54. package/dist/src/modular/buildOperations.js.map +1 -1
  55. package/dist/src/modular/buildRestorePoller.d.ts +3 -0
  56. package/dist/src/modular/buildRestorePoller.d.ts.map +1 -0
  57. package/dist/src/modular/buildRestorePoller.js +203 -0
  58. package/dist/src/modular/buildRestorePoller.js.map +1 -0
  59. package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
  60. package/dist/src/modular/buildRootIndex.js +37 -0
  61. package/dist/src/modular/buildRootIndex.js.map +1 -1
  62. package/dist/src/modular/emitLoggerFile.d.ts +4 -0
  63. package/dist/src/modular/emitLoggerFile.d.ts.map +1 -0
  64. package/dist/src/modular/emitLoggerFile.js +16 -0
  65. package/dist/src/modular/emitLoggerFile.js.map +1 -0
  66. package/dist/src/modular/emitModels.d.ts.map +1 -1
  67. package/dist/src/modular/emitModels.js +0 -5
  68. package/dist/src/modular/emitModels.js.map +1 -1
  69. package/dist/src/modular/external-dependencies.d.ts +26 -0
  70. package/dist/src/modular/external-dependencies.d.ts.map +1 -0
  71. package/dist/src/modular/external-dependencies.js +137 -0
  72. package/dist/src/modular/external-dependencies.js.map +1 -0
  73. package/dist/src/modular/helpers/clientHelpers.d.ts +13 -6
  74. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  75. package/dist/src/modular/helpers/clientHelpers.js +92 -7
  76. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  77. package/dist/src/modular/helpers/operationHelpers.d.ts +6 -1
  78. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  79. package/dist/src/modular/helpers/operationHelpers.js +43 -69
  80. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  81. package/dist/src/modular/helpers/typeHelpers.d.ts +1 -0
  82. package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
  83. package/dist/src/modular/helpers/typeHelpers.js +6 -0
  84. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  85. package/dist/src/modular/interfaces.d.ts +1 -0
  86. package/dist/src/modular/interfaces.d.ts.map +1 -1
  87. package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -1
  88. package/dist/src/modular/serialization/buildSerializerFunction.js +2 -20
  89. package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
  90. package/dist/src/modular/static-helpers-metadata.d.ts +72 -0
  91. package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -0
  92. package/dist/src/modular/static-helpers-metadata.js +72 -0
  93. package/dist/src/modular/static-helpers-metadata.js.map +1 -0
  94. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  95. package/dist/src/transform/transfromRLCOptions.js +56 -49
  96. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  97. package/dist/src/utils/credentialUtils.d.ts +10 -0
  98. package/dist/src/utils/credentialUtils.d.ts.map +1 -0
  99. package/dist/src/utils/credentialUtils.js +37 -0
  100. package/dist/src/utils/credentialUtils.js.map +1 -0
  101. package/dist/src/utils/dirname.d.ts +9 -0
  102. package/dist/src/utils/dirname.d.ts.map +1 -0
  103. package/dist/src/utils/dirname.js +12 -0
  104. package/dist/src/utils/dirname.js.map +1 -0
  105. package/dist/src/utils/emitUtil.d.ts.map +1 -1
  106. package/dist/src/utils/emitUtil.js +3 -5
  107. package/dist/src/utils/emitUtil.js.map +1 -1
  108. package/dist/src/utils/modelUtils.d.ts +1 -1
  109. package/dist/src/utils/modelUtils.js +3 -2
  110. package/dist/src/utils/modelUtils.js.map +1 -1
  111. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  112. package/dist/src/utils/operationUtil.js +20 -2
  113. package/dist/src/utils/operationUtil.js.map +1 -1
  114. package/dist/src/utils/resolve-project-root.d.ts +7 -0
  115. package/dist/src/utils/resolve-project-root.d.ts.map +1 -0
  116. package/dist/src/utils/resolve-project-root.js +22 -0
  117. package/dist/src/utils/resolve-project-root.js.map +1 -0
  118. package/dist/tsconfig.tsbuildinfo +1 -1
  119. package/package.json +29 -25
  120. package/src/contextManager.ts +2 -0
  121. package/src/framework/dependency.ts +56 -0
  122. package/src/framework/hooks/binder.ts +144 -27
  123. package/src/framework/hooks/useDependencies.ts +18 -0
  124. package/src/framework/load-static-helpers.ts +174 -0
  125. package/src/framework/reference.ts +27 -3
  126. package/src/framework/sample.ts +1 -1
  127. package/src/index.ts +154 -113
  128. package/src/lib.ts +8 -1
  129. package/src/modular/buildClassicalClient.ts +14 -12
  130. package/src/modular/buildClassicalOperationGroups.ts +1 -24
  131. package/src/modular/buildClientContext.ts +93 -63
  132. package/src/modular/buildCodeModel.ts +93 -128
  133. package/src/modular/buildHelperSerializers.ts +1 -0
  134. package/src/modular/buildOperations.ts +9 -110
  135. package/src/modular/buildRestorePoller.ts +239 -0
  136. package/src/modular/buildRootIndex.ts +68 -0
  137. package/src/modular/emitLoggerFile.ts +28 -0
  138. package/src/modular/emitModels.ts +0 -8
  139. package/src/modular/external-dependencies.ts +140 -0
  140. package/src/modular/helpers/clientHelpers.ts +148 -14
  141. package/src/modular/helpers/operationHelpers.ts +72 -109
  142. package/src/modular/helpers/typeHelpers.ts +8 -0
  143. package/src/modular/interfaces.ts +1 -0
  144. package/src/modular/serialization/buildSerializerFunction.ts +3 -33
  145. package/src/modular/static-helpers-metadata.ts +73 -0
  146. package/src/transform/transfromRLCOptions.ts +61 -53
  147. package/src/utils/credentialUtils.ts +41 -0
  148. package/src/utils/dirname.ts +12 -0
  149. package/src/utils/emitUtil.ts +3 -2
  150. package/src/utils/modelUtils.ts +4 -4
  151. package/src/utils/operationUtil.ts +25 -2
  152. package/src/utils/resolve-project-root.ts +28 -0
  153. package/static/static-helpers/pagingHelpers.ts +274 -0
  154. package/static/static-helpers/pollingHelpers.ts +137 -0
  155. package/static/static-helpers/serialization/build-csv-collection.ts +6 -0
  156. package/static/static-helpers/serialization/build-multi-collection.ts +13 -0
  157. package/static/static-helpers/serialization/build-pipe-collection.ts +3 -0
  158. package/static/static-helpers/serialization/build-ssv-collection.ts +3 -0
  159. package/static/static-helpers/serialization/build-tsv-collection.ts +3 -0
  160. package/dist/src/modular/buildLroFiles.d.ts +0 -24
  161. package/dist/src/modular/buildLroFiles.d.ts.map +0 -1
  162. package/dist/src/modular/buildLroFiles.js +0 -393
  163. package/dist/src/modular/buildLroFiles.js.map +0 -1
  164. package/dist/src/modular/buildPagingFiles.d.ts +0 -4
  165. package/dist/src/modular/buildPagingFiles.d.ts.map +0 -1
  166. package/dist/src/modular/buildPagingFiles.js +0 -333
  167. package/dist/src/modular/buildPagingFiles.js.map +0 -1
  168. package/src/modular/buildLroFiles.ts +0 -429
  169. package/src/modular/buildPagingFiles.ts +0 -356
@@ -1,15 +1,17 @@
1
1
  import {
2
2
  getImportSpecifier,
3
+ PackageFlavor,
3
4
  Imports as RuntimeImports
4
5
  } from "@azure-tools/rlc-common";
5
6
  import {
6
7
  OptionalKind,
7
8
  ParameterDeclarationStructure,
8
- SourceFile
9
+ SourceFile,
10
+ StatementedNode
9
11
  } from "ts-morph";
10
- import { Client } from "../modularCodeModel.js";
12
+ import { Client, ModularCodeModel } from "../modularCodeModel.js";
11
13
  import { getClientName } from "./namingHelpers.js";
12
- import { getType } from "./typeHelpers.js";
14
+ import { getType, isCredentialType } from "./typeHelpers.js";
13
15
  import { SdkContext } from "../../utils/interfaces.js";
14
16
 
15
17
  export function getClientParameters(
@@ -58,10 +60,147 @@ export function getClientParameters(
58
60
  return params;
59
61
  }
60
62
 
61
- export function getUserAgentStatements(
62
- sdkUserAgentPrefix: string,
63
- paramNames: string[]
64
- ): { userAgentStatements: string; updatedParamNames: string[] } {
63
+ export function buildGetClientEndpointParam(
64
+ context: StatementedNode,
65
+ client: Client
66
+ ): string {
67
+ // Special case: endpoint URL not defined
68
+ if (client.url === "") {
69
+ const endpointParam = client.parameters.find(
70
+ (x) => x.location === "endpointPath"
71
+ );
72
+ return `options.endpoint ?? options.baseUrl ?? ${endpointParam?.clientName}`;
73
+ }
74
+
75
+ const urlParams = client.parameters.filter(
76
+ (x) => x.location === "path" || x.location === "endpointPath"
77
+ );
78
+
79
+ for (const param of urlParams) {
80
+ if (param.clientDefaultValue) {
81
+ const defaultValue =
82
+ typeof param.clientDefaultValue === "string"
83
+ ? `"${param.clientDefaultValue}"`
84
+ : param.clientDefaultValue;
85
+ context.addStatements(
86
+ `const ${param.clientName} = options.${param.clientName} ?? ${defaultValue};`
87
+ );
88
+ } else if (param.optional) {
89
+ context.addStatements(
90
+ `const ${param.clientName} = options.${param.clientName};`
91
+ );
92
+ }
93
+ }
94
+
95
+ let parameterizedEndpointUrl = client.url;
96
+ for (const param of urlParams) {
97
+ parameterizedEndpointUrl = parameterizedEndpointUrl.replace(
98
+ `{${param.restApiName}}`,
99
+ `\${${param.clientName}}`
100
+ );
101
+ }
102
+
103
+ context.addStatements(
104
+ `const endpointUrl = options.endpoint ?? options.baseUrl ?? \`${parameterizedEndpointUrl}\``
105
+ );
106
+ return "endpointUrl";
107
+ }
108
+
109
+ /**
110
+ * Builds the options to be passed to getClient
111
+ *
112
+ * @param context - context in which the options are being passed; statements will be added to this context
113
+ * to help build the options shape
114
+ * @returns - an expression representing the options to be passed in to getClient
115
+ */
116
+ export function buildGetClientOptionsParam(
117
+ context: StatementedNode,
118
+ codeModel: ModularCodeModel,
119
+ endpointParam: string
120
+ ): string {
121
+ const userAgentOptions = buildUserAgentOptions(context, "azsdk-js-api");
122
+ const loggingOptions = buildLoggingOptions(codeModel.options.flavor);
123
+ const credentials = buildCredentials(codeModel, endpointParam);
124
+
125
+ let expr = "const { apiVersion: _, ...updatedOptions } = {";
126
+
127
+ expr += "...options,";
128
+
129
+ if (userAgentOptions) {
130
+ expr += `userAgentOptions: ${userAgentOptions},`;
131
+ }
132
+ if (loggingOptions) {
133
+ expr += `loggingOptions: ${loggingOptions},`;
134
+ }
135
+ if (credentials) {
136
+ expr += `credentials: ${credentials},`;
137
+ }
138
+
139
+ expr += `}`;
140
+
141
+ context.addStatements(expr);
142
+ return "updatedOptions";
143
+ }
144
+
145
+ export function buildGetClientCredentialParam(
146
+ client: Client,
147
+ codeModel: ModularCodeModel
148
+ ): string {
149
+ if (
150
+ codeModel.options.addCredentials &&
151
+ (codeModel.options.credentialScopes ||
152
+ codeModel.options.credentialKeyHeaderName)
153
+ ) {
154
+ return (
155
+ client.parameters.find((x) => isCredentialType(x.type))?.clientName ??
156
+ "undefined"
157
+ );
158
+ } else {
159
+ return "undefined";
160
+ }
161
+ }
162
+
163
+ function buildCredentials(
164
+ codeModel: ModularCodeModel,
165
+ endpointParam: string
166
+ ): string | undefined {
167
+ if (!codeModel.options.addCredentials) {
168
+ return undefined;
169
+ }
170
+
171
+ const { credentialScopes, credentialKeyHeaderName } = codeModel.options;
172
+
173
+ const scopesString = credentialScopes
174
+ ? credentialScopes.map((cs) => `"${cs}"`).join(", ") ||
175
+ `\`\${${endpointParam}}/.default\``
176
+ : "";
177
+ const scopes = scopesString
178
+ ? `scopes: options.credentials?.scopes ?? [${scopesString}],`
179
+ : "";
180
+
181
+ const apiKeyHeaderName = credentialKeyHeaderName
182
+ ? `apiKeyHeaderName: options.credentials?.apiKeyHeaderName ?? "${credentialKeyHeaderName}",`
183
+ : "";
184
+
185
+ if (!scopes && !apiKeyHeaderName) {
186
+ return undefined;
187
+ }
188
+
189
+ return `{ ${scopes}${apiKeyHeaderName} }`;
190
+ }
191
+
192
+ function buildLoggingOptions(flavor?: PackageFlavor): string | undefined {
193
+ if (flavor !== "azure") {
194
+ return undefined;
195
+ }
196
+
197
+ return `{ logger: options.loggingOptions?.logger ?? logger.info }`;
198
+ }
199
+
200
+ export function buildUserAgentOptions(
201
+ context: StatementedNode,
202
+ sdkUserAgentPrefix: string
203
+ ): string {
65
204
  const userAgentStatements = `
66
205
  const prefixFromOptions = options?.userAgentOptions?.userAgentPrefix;
67
206
  const userAgentPrefix = ${
@@ -72,14 +211,9 @@ export function getUserAgentStatements(
72
211
  };
73
212
  `;
74
213
 
75
- // Update param names to spread over options
76
- const updatedParamNames = paramNames.map((x) =>
77
- x === "options"
78
- ? "{ ...options, userAgentOptions: { userAgentPrefix } }"
79
- : x
80
- );
214
+ context.addStatements(userAgentStatements);
81
215
 
82
- return { userAgentStatements, updatedParamNames };
216
+ return `{ userAgentPrefix }`;
83
217
  }
84
218
 
85
219
  export function importCredential(
@@ -1,10 +1,7 @@
1
1
  import {
2
2
  addImportToSpecifier,
3
- getResponseBaseName,
4
- getResponseTypeName,
5
3
  Imports as RuntimeImports,
6
- NameType,
7
- OperationResponse
4
+ NameType
8
5
  } from "@azure-tools/rlc-common";
9
6
  import {
10
7
  SdkContext,
@@ -37,7 +34,6 @@ import {
37
34
  Operation,
38
35
  Parameter,
39
36
  Property,
40
- Response,
41
37
  Type
42
38
  } from "../modularCodeModel.js";
43
39
  import {
@@ -46,57 +42,9 @@ import {
46
42
  } from "./docsHelpers.js";
47
43
  import { getClassicalLayerPrefix, getOperationName } from "./namingHelpers.js";
48
44
  import { buildType, isTypeNullable } from "./typeHelpers.js";
49
-
50
- function getRLCResponseTypes(rlcResponse?: OperationResponse) {
51
- if (!rlcResponse?.responses) {
52
- return;
53
- }
54
- return rlcResponse?.responses
55
- .map(
56
- (resp) =>
57
- resp.predefinedName ?? getRLCResponseType(resp.statusCode, rlcResponse)
58
- )
59
- .join(" | ");
60
- }
61
-
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)
98
- );
99
- }
45
+ import { resolveReference } from "../../framework/reference.js";
46
+ import { PagingHelpers, PollingHelpers } from "../static-helpers-metadata.js";
47
+ import { AzurePollingDependencies } from "../external-dependencies.js";
100
48
 
101
49
  export function getSendPrivateFunction(
102
50
  dpgContext: SdkContext,
@@ -106,16 +54,13 @@ export function getSendPrivateFunction(
106
54
  ): OptionalKind<FunctionDeclarationStructure> {
107
55
  const parameters = getOperationSignatureParameters(operation, clientType);
108
56
  const { name } = getOperationName(operation);
109
- const returnType = `StreamableMethod<${getRLCResponseTypes(
110
- operation.rlcResponse
111
- )}>`;
112
57
 
113
58
  const functionStatement: OptionalKind<FunctionDeclarationStructure> = {
114
59
  isAsync: false,
115
60
  isExported: true,
116
61
  name: `_${name}Send`,
117
62
  parameters,
118
- returnType
63
+ returnType: "StreamableMethod"
119
64
  };
120
65
 
121
66
  const operationPath = operation.url;
@@ -132,7 +77,7 @@ export function getSendPrivateFunction(
132
77
  dpgContext,
133
78
  operation,
134
79
  runtimeImports
135
- )}}) ${operation.isOverload ? `as ${returnType}` : ``} ;`
80
+ )}});`
136
81
  );
137
82
 
138
83
  return {
@@ -143,22 +88,23 @@ export function getSendPrivateFunction(
143
88
 
144
89
  export function getDeserializePrivateFunction(
145
90
  operation: Operation,
146
- needSubClient: boolean,
147
- needUnexpectedHelper: boolean,
148
91
  runtimeImports: RuntimeImports
149
92
  ): OptionalKind<FunctionDeclarationStructure> {
150
93
  const { name } = getOperationName(operation);
151
94
  const parameters: OptionalKind<ParameterDeclarationStructure>[] = [
152
95
  {
153
96
  name: "result",
154
- type: getRLCResponseTypes(operation.rlcResponse)
97
+ type: "PathUncheckedResponse"
155
98
  }
156
99
  ];
100
+ addImportToSpecifier("restClient", runtimeImports, "PathUncheckedResponse");
101
+
157
102
  // TODO: Support LRO + paging operation
158
103
  // https://github.com/Azure/autorest.typescript/issues/2313
159
104
  const isLroOnly = isLroOnlyOperation(operation);
160
105
 
161
106
  // TODO: Support operation overloads
107
+ // TODO: Support multiple responses
162
108
  const response = operation.responses[0]!;
163
109
  let returnType;
164
110
  if (isLroOnly && operation.method.toLowerCase() !== "patch") {
@@ -181,48 +127,23 @@ export function getDeserializePrivateFunction(
181
127
  returnType: `Promise<${returnType.type}>`
182
128
  };
183
129
  const statements: string[] = [];
184
- if (needUnexpectedHelper) {
185
- statements.push(
186
- `if(${needSubClient ? "UnexpectedHelper." : ""}isUnexpected(result)){`,
187
- `throw createRestError(result);`,
188
- "}"
189
- );
190
- addImportToSpecifier("restClient", runtimeImports, "createRestError");
191
- } else {
192
- const validStatus = [
193
- ...new Set(
194
- operation.responses
195
- .flatMap((r) => r.statusCodes)
196
- .filter((s) => s !== "default")
197
- )
198
- ];
199
-
200
- if (validStatus.length > 0) {
201
- statements.push(
202
- `if(${validStatus
203
- .map((s) => `result.status !== "${s}"`)
204
- .join(" || ")}){`,
205
- `throw createRestError(result);`,
206
- "}"
207
- );
208
- addImportToSpecifier("restClient", runtimeImports, "createRestError");
209
- }
210
- }
130
+
131
+ statements.push(
132
+ `const expectedStatuses = ${getExpectedStatuses(operation)};`
133
+ );
134
+ statements.push(
135
+ `if(!expectedStatuses.includes(result.status)){`,
136
+ `throw createRestError(result);`,
137
+ "}"
138
+ );
139
+ addImportToSpecifier("restClient", runtimeImports, "createRestError");
211
140
 
212
141
  const deserializedType = isLroOnly
213
142
  ? operation?.lroMetadata?.finalResult
214
143
  : response.type;
215
144
  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";
225
- }
145
+
146
+ const deserializePrefix = "result.body";
226
147
 
227
148
  const deserializedRoot = hasLroSubPath
228
149
  ? `${deserializePrefix}.${operation?.lroMetadata?.finalResultPath}`
@@ -394,6 +315,12 @@ function getLroOnlyOperationFunction(operation: Operation, clientType: string) {
394
315
  getOperationSignatureParameters(operation, clientType);
395
316
  const returnType = buildLroReturnType(operation);
396
317
  const { name, fixme = [] } = getOperationName(operation);
318
+ const pollerLikeReference = resolveReference(
319
+ AzurePollingDependencies.PollerLike
320
+ );
321
+ const operationStateReference = resolveReference(
322
+ AzurePollingDependencies.OperationState
323
+ );
397
324
  const functionStatement = {
398
325
  docs: [
399
326
  ...getDocsFromDescription(operation.description),
@@ -404,18 +331,27 @@ function getLroOnlyOperationFunction(operation: Operation, clientType: string) {
404
331
  name,
405
332
  propertyName: operation.name,
406
333
  parameters,
407
- returnType: `PollerLike<OperationState<${returnType.type}>, ${returnType.type}>`
334
+ returnType: `${pollerLikeReference}<${operationStateReference}<${returnType.type}>, ${returnType.type}>`
408
335
  };
409
336
 
337
+ const getLongRunningPollerReference = resolveReference(
338
+ PollingHelpers.GetLongRunningPoller
339
+ );
340
+
410
341
  const statements: string[] = [];
411
342
  statements.push(`
412
- return getLongRunningPoller(context, _${name}Deserialize, {
343
+
344
+ return ${getLongRunningPollerReference}(context, _${name}Deserialize, ${getExpectedStatuses(
345
+ operation
346
+ )}, {
413
347
  updateIntervalInMs: options?.updateIntervalInMs,
414
348
  abortSignal: options?.abortSignal,
415
349
  getInitialResponse: () => _${name}Send(${parameters
416
350
  .map((p) => p.name)
417
351
  .join(", ")})
418
- }) as PollerLike<OperationState<${returnType.type}>, ${returnType.type}>;
352
+ }) as ${pollerLikeReference}<${operationStateReference}<${
353
+ returnType.type
354
+ }>, ${returnType.type}>;
419
355
  `);
420
356
 
421
357
  return {
@@ -450,6 +386,12 @@ function getPagingOnlyOperationFunction(
450
386
  returnType = buildType(type.name, type, type.format);
451
387
  }
452
388
  const { name, fixme = [] } = getOperationName(operation);
389
+ const pagedAsyncIterableIteratorReference = resolveReference(
390
+ PagingHelpers.PagedAsyncIterableIterator
391
+ );
392
+ const buildPagedAsyncIteratorReference = resolveReference(
393
+ PagingHelpers.BuildPagedAsyncIterator
394
+ );
453
395
  const functionStatement = {
454
396
  docs: [
455
397
  ...getDocsFromDescription(operation.description),
@@ -460,7 +402,7 @@ function getPagingOnlyOperationFunction(
460
402
  name,
461
403
  propertyName: operation.name,
462
404
  parameters,
463
- returnType: `PagedAsyncIterableIterator<${returnType.type}>`
405
+ returnType: `${pagedAsyncIterableIteratorReference}<${returnType.type}>`
464
406
  };
465
407
 
466
408
  const statements: string[] = [];
@@ -472,10 +414,11 @@ function getPagingOnlyOperationFunction(
472
414
  options.push(`nextLinkName: "${operation.continuationTokenName}"`);
473
415
  }
474
416
  statements.push(
475
- `return buildPagedAsyncIterator(
417
+ `return ${buildPagedAsyncIteratorReference}(
476
418
  context,
477
419
  () => _${name}Send(${parameters.map((p) => p.name).join(", ")}),
478
420
  _${name}Deserialize,
421
+ ${getExpectedStatuses(operation)},
479
422
  ${options.length > 0 ? `{${options.join(", ")}}` : ``}
480
423
  );`
481
424
  );
@@ -1243,7 +1186,7 @@ export function deserializeResponseValue(
1243
1186
  isTypeNullable(type.elementType) || type.elementType.optional
1244
1187
  ? "!p ? p :"
1245
1188
  : "";
1246
- return `${prefix}.map(p => { return ${elementNullOrUndefinedPrefix}{${getResponseMapping(
1189
+ return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}{${getResponseMapping(
1247
1190
  type.elementType,
1248
1191
  "p",
1249
1192
  runtimeImports,
@@ -1258,14 +1201,14 @@ export function deserializeResponseValue(
1258
1201
  type.elementType,
1259
1202
  "deserialize"
1260
1203
  );
1261
- return `${prefix}.map(p => ${nullOrUndefinedPrefix}${deserializeFunctionName}(p))`;
1204
+ return `${prefix}.map((p: any) => ${nullOrUndefinedPrefix}${deserializeFunctionName}(p))`;
1262
1205
  }
1263
1206
  return `${prefix}`;
1264
1207
  } else if (
1265
1208
  needsDeserialize(type.elementType) &&
1266
1209
  !type.elementType?.aliasType
1267
1210
  ) {
1268
- return `${prefix}.map(p => ${deserializeResponseValue(
1211
+ return `${prefix}.map((p: any) => ${deserializeResponseValue(
1269
1212
  type.elementType!,
1270
1213
  "p",
1271
1214
  runtimeImports,
@@ -1554,3 +1497,23 @@ export function isDiscriminatedUnion(type?: SdkType): type is SdkModelType {
1554
1497
  type.discriminatedSubtypes
1555
1498
  );
1556
1499
  }
1500
+
1501
+ /**
1502
+ * Get an expression representing an array of expected status codes for the operation
1503
+ * @param operation The operation
1504
+ */
1505
+ export function getExpectedStatuses(operation: Operation): string {
1506
+ const statusCodes = operation.responses.flatMap((x) =>
1507
+ x.statusCodes.filter((s) => s !== "default")
1508
+ );
1509
+ // LROs may call the same path but with GET to get the operation status.
1510
+ if (
1511
+ isLroOnlyOperation(operation) &&
1512
+ operation.method !== "GET" &&
1513
+ !statusCodes.includes(200)
1514
+ ) {
1515
+ statusCodes.push(200);
1516
+ }
1517
+
1518
+ return `[${statusCodes.map((x) => `"${x}"`).join(", ")}]`;
1519
+ }
@@ -298,3 +298,11 @@ export function isNumericTypeKind(kind: string): boolean {
298
298
  export function isDateTimeTypeKind(kind: string): boolean {
299
299
  return DateTimeTypeKinds.includes(kind);
300
300
  }
301
+
302
+ export function isCredentialType(type: Type): boolean {
303
+ const credentialTypes = ["OAuth2", "Key"];
304
+ return (
305
+ credentialTypes.includes(type.type) ||
306
+ (type.type === "combined" && (type.types?.every(isCredentialType) ?? false))
307
+ );
308
+ }
@@ -11,6 +11,7 @@ export interface ClientDetails {
11
11
 
12
12
  export interface OperationPathAndDeserDetails {
13
13
  path: string;
14
+ expectedStatusesExpression: string;
14
15
  deserName: string;
15
16
  renamedDeserName?: string;
16
17
  }
@@ -1,13 +1,8 @@
1
1
  import { toCamelCase, toPascalCase } from "../../utils/casingUtils.js";
2
2
  import { Type as ModularType } from "../modularCodeModel.js";
3
3
  import { getRequestModelMapping } from "../helpers/operationHelpers.js";
4
- import { useContext } from "../../contextManager.js";
5
4
 
6
- import {
7
- Imports as RuntimeImports,
8
- SchemaContext,
9
- addImportToSpecifier
10
- } from "@azure-tools/rlc-common";
5
+ import { Imports as RuntimeImports } from "@azure-tools/rlc-common";
11
6
  import { UsageFlags } from "@typespec/compiler";
12
7
  import {
13
8
  SdkModelType,
@@ -24,7 +19,6 @@ export function buildModelSerializer(
24
19
  type: ModularType,
25
20
  runtimeImports: RuntimeImports
26
21
  ): string | undefined {
27
- const rlcMetadata = useContext("rlcMetaTree");
28
22
  const modelTcgcType = getTcgcType(type) as SdkModelType;
29
23
  if (
30
24
  modelTcgcType.usage !== undefined &&
@@ -39,9 +33,6 @@ export function buildModelSerializer(
39
33
 
40
34
  let serializerName = `${toCamelCase(type.name)}Serializer`;
41
35
 
42
- const restModel = rlcMetadata.get(type.__raw!);
43
- const restModelName = restModel?.rlcType.name;
44
-
45
36
  const output: string[] = [];
46
37
 
47
38
  if (
@@ -85,17 +76,6 @@ export function buildModelSerializer(
85
76
  serializerName = baseSerializerName;
86
77
  }
87
78
 
88
- let serializerReturnType = "";
89
-
90
- // There are some situations where the type is not present in the REST API,
91
- // this can happen when client.tsp overrides visibility to public on an orphan model
92
- // In this case we just let TypeScript infer the return type.
93
- let restModelNameAlias = "";
94
- if (restModelName && restModel.rlcType.usage?.includes(SchemaContext.Input)) {
95
- restModelNameAlias = `${restModelName}Rest`;
96
- serializerReturnType = `: ${restModelNameAlias}`;
97
- }
98
-
99
79
  if (type.type === "model" || type.type === "dict") {
100
80
  const nullabilityPrefix = "";
101
81
  // getPropertySerializationPrefix({
@@ -127,18 +107,10 @@ export function buildModelSerializer(
127
107
  output.push(`
128
108
  export function ${serializerName}(item: ${toPascalCase(
129
109
  type.name
130
- )})${serializerReturnType} {
110
+ )}): Record<string, unknown> {
131
111
  return ${fnBody}
132
112
  }
133
113
  `);
134
-
135
- if (serializerReturnType) {
136
- addImportToSpecifier(
137
- "rlcIndex",
138
- runtimeImports,
139
- `${restModelName} as ${restModelNameAlias}`
140
- );
141
- }
142
114
  } else {
143
115
  output.push(`
144
116
  export function ${serializerName}(item: ${toPascalCase(type.name)}) {
@@ -148,9 +120,7 @@ export function buildModelSerializer(
148
120
  }
149
121
  } else if (type.type === "enum") {
150
122
  output.push(`
151
- export function ${serializerName}(item: ${toPascalCase(
152
- type.name
153
- )})${serializerReturnType} {
123
+ export function ${serializerName}(item: ${toPascalCase(type.name)}) {
154
124
  return item;
155
125
  }
156
126
  `);
@@ -0,0 +1,73 @@
1
+ export const SerializationHelpers = {
2
+ buildMultiCollection: {
3
+ kind: "function",
4
+ name: "buildMultiCollection",
5
+ location: "serialization/build-multi-collection.ts"
6
+ },
7
+ buildCsvCollection: {
8
+ kind: "function",
9
+ name: "buildCsvCollection",
10
+ location: "serialization/build-csv-collection.ts"
11
+ },
12
+ buildPipeCollection: {
13
+ kind: "function",
14
+ name: "buildPipeCollection",
15
+ location: "serialization/build-pipe-collection.ts"
16
+ },
17
+ buildSsvCollection: {
18
+ kind: "function",
19
+ name: "buildSsvCollection",
20
+ location: "serialization/build-ssv-collection.ts"
21
+ },
22
+ buildTsvCollection: {
23
+ kind: "function",
24
+ name: "buildTsvCollection",
25
+ location: "serialization/build-tsv-collection.ts"
26
+ }
27
+ } as const;
28
+
29
+ export const PagingHelpers = {
30
+ PageSettings: {
31
+ kind: "interface",
32
+ name: "PageSettings",
33
+ location: "pagingHelpers.ts"
34
+ },
35
+ ContinuablePage: {
36
+ kind: "typeAlias",
37
+ name: "ContinuablePage",
38
+ location: "pagingHelpers.ts"
39
+ },
40
+ PagedAsyncIterableIterator: {
41
+ kind: "interface",
42
+ name: "PagedAsyncIterableIterator",
43
+ location: "pagingHelpers.ts"
44
+ },
45
+ PagedResult: {
46
+ kind: "interface",
47
+ name: "PagedResult",
48
+ location: "pagingHelpers.ts"
49
+ },
50
+ BuildPagedAsyncIteratorOptions: {
51
+ kind: "interface",
52
+ name: "BuildPagedAsyncIteratorOptions",
53
+ location: "pagingHelpers.ts"
54
+ },
55
+ BuildPagedAsyncIterator: {
56
+ kind: "function",
57
+ name: "buildPagedAsyncIterator",
58
+ location: "pagingHelpers.ts"
59
+ }
60
+ } as const;
61
+
62
+ export const PollingHelpers = {
63
+ GetLongRunningPollerOptions: {
64
+ kind: "interface",
65
+ name: "GetLongRunningPollerOptions",
66
+ location: "pollingHelpers.ts"
67
+ },
68
+ GetLongRunningPoller: {
69
+ kind: "function",
70
+ name: "getLongRunningPoller",
71
+ location: "pollingHelpers.ts"
72
+ }
73
+ } as const;