@azure-tools/rlc-common 1.0.0-beta.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 (209) hide show
  1. package/.rush/temp/package-deps_build.json +45 -0
  2. package/.rush/temp/shrinkwrap-deps.json +72 -0
  3. package/CHANGELOG.md +3 -0
  4. package/dist/buildClient.js +198 -0
  5. package/dist/buildClient.js.map +1 -0
  6. package/dist/buildClientDefinitions.js +160 -0
  7. package/dist/buildClientDefinitions.js.map +1 -0
  8. package/dist/buildIndexFile.js +150 -0
  9. package/dist/buildIndexFile.js.map +1 -0
  10. package/dist/buildIsUnexpectedHelper.js +219 -0
  11. package/dist/buildIsUnexpectedHelper.js.map +1 -0
  12. package/dist/buildMethodShortcuts.js +50 -0
  13. package/dist/buildMethodShortcuts.js.map +1 -0
  14. package/dist/buildObjectTypes.js +250 -0
  15. package/dist/buildObjectTypes.js.map +1 -0
  16. package/dist/buildPaginateHelper.js +30 -0
  17. package/dist/buildPaginateHelper.js.map +1 -0
  18. package/dist/buildParameterTypes.js +287 -0
  19. package/dist/buildParameterTypes.js.map +1 -0
  20. package/dist/buildPollingHelper.js +21 -0
  21. package/dist/buildPollingHelper.js.map +1 -0
  22. package/dist/buildResponseTypes.js +122 -0
  23. package/dist/buildResponseTypes.js.map +1 -0
  24. package/dist/buildSchemaType.js +44 -0
  25. package/dist/buildSchemaType.js.map +1 -0
  26. package/dist/buildTopLevelIndexFile.js +45 -0
  27. package/dist/buildTopLevelIndexFile.js.map +1 -0
  28. package/dist/helpers/nameConstructors.js +41 -0
  29. package/dist/helpers/nameConstructors.js.map +1 -0
  30. package/dist/helpers/nameUtils.js +196 -0
  31. package/dist/helpers/nameUtils.js.map +1 -0
  32. package/dist/helpers/operationHelpers.js +83 -0
  33. package/dist/helpers/operationHelpers.js.map +1 -0
  34. package/dist/helpers/schemaHelpers.js +27 -0
  35. package/dist/helpers/schemaHelpers.js.map +1 -0
  36. package/dist/helpers/shortcutMethods.js +46 -0
  37. package/dist/helpers/shortcutMethods.js.map +1 -0
  38. package/dist/index.js +44 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/interfaces.js +18 -0
  41. package/dist/interfaces.js.map +1 -0
  42. package/dist/metadata/buildApiExtractorConfig.js +56 -0
  43. package/dist/metadata/buildApiExtractorConfig.js.map +1 -0
  44. package/dist/metadata/buildESLintConfig.js +33 -0
  45. package/dist/metadata/buildESLintConfig.js.map +1 -0
  46. package/dist/metadata/buildLicenseFile.js +41 -0
  47. package/dist/metadata/buildLicenseFile.js.map +1 -0
  48. package/dist/metadata/buildPackageFile.js +232 -0
  49. package/dist/metadata/buildPackageFile.js.map +1 -0
  50. package/dist/metadata/buildReadmeFile.js +170 -0
  51. package/dist/metadata/buildReadmeFile.js.map +1 -0
  52. package/dist/metadata/buildRollupConfig.js +144 -0
  53. package/dist/metadata/buildRollupConfig.js.map +1 -0
  54. package/dist/metadata/buildTsConfig.js +72 -0
  55. package/dist/metadata/buildTsConfig.js.map +1 -0
  56. package/dist/package.json +1 -0
  57. package/dist/static/paginateContent.js +214 -0
  58. package/dist/static/paginateContent.js.map +1 -0
  59. package/dist/static/pollingContent.js +78 -0
  60. package/dist/static/pollingContent.js.map +1 -0
  61. package/dist/test/buildEnvFile.js +31 -0
  62. package/dist/test/buildEnvFile.js.map +1 -0
  63. package/dist/test/buildKarmaConfig.js +19 -0
  64. package/dist/test/buildKarmaConfig.js.map +1 -0
  65. package/dist/test/buildRecordedClient.js +22 -0
  66. package/dist/test/buildRecordedClient.js.map +1 -0
  67. package/dist/test/buildSampleTest.js +19 -0
  68. package/dist/test/buildSampleTest.js.map +1 -0
  69. package/dist/test/template.js +192 -0
  70. package/dist/test/template.js.map +1 -0
  71. package/dist-esm/buildClient.js +191 -0
  72. package/dist-esm/buildClient.js.map +1 -0
  73. package/dist-esm/buildClientDefinitions.js +155 -0
  74. package/dist-esm/buildClientDefinitions.js.map +1 -0
  75. package/dist-esm/buildIndexFile.js +145 -0
  76. package/dist-esm/buildIndexFile.js.map +1 -0
  77. package/dist-esm/buildIsUnexpectedHelper.js +215 -0
  78. package/dist-esm/buildIsUnexpectedHelper.js.map +1 -0
  79. package/dist-esm/buildMethodShortcuts.js +46 -0
  80. package/dist-esm/buildMethodShortcuts.js.map +1 -0
  81. package/dist-esm/buildObjectTypes.js +249 -0
  82. package/dist-esm/buildObjectTypes.js.map +1 -0
  83. package/dist-esm/buildPaginateHelper.js +26 -0
  84. package/dist-esm/buildPaginateHelper.js.map +1 -0
  85. package/dist-esm/buildParameterTypes.js +288 -0
  86. package/dist-esm/buildParameterTypes.js.map +1 -0
  87. package/dist-esm/buildPollingHelper.js +17 -0
  88. package/dist-esm/buildPollingHelper.js.map +1 -0
  89. package/dist-esm/buildResponseTypes.js +127 -0
  90. package/dist-esm/buildResponseTypes.js.map +1 -0
  91. package/dist-esm/buildSchemaType.js +39 -0
  92. package/dist-esm/buildSchemaType.js.map +1 -0
  93. package/dist-esm/buildTopLevelIndexFile.js +41 -0
  94. package/dist-esm/buildTopLevelIndexFile.js.map +1 -0
  95. package/dist-esm/helpers/nameConstructors.js +34 -0
  96. package/dist-esm/helpers/nameConstructors.js.map +1 -0
  97. package/dist-esm/helpers/nameUtils.js +187 -0
  98. package/dist-esm/helpers/nameUtils.js.map +1 -0
  99. package/dist-esm/helpers/operationHelpers.js +72 -0
  100. package/dist-esm/helpers/operationHelpers.js.map +1 -0
  101. package/dist-esm/helpers/schemaHelpers.js +21 -0
  102. package/dist-esm/helpers/schemaHelpers.js.map +1 -0
  103. package/dist-esm/helpers/shortcutMethods.js +42 -0
  104. package/dist-esm/helpers/shortcutMethods.js.map +1 -0
  105. package/dist-esm/index.js +28 -0
  106. package/dist-esm/index.js.map +1 -0
  107. package/dist-esm/interfaces.js +15 -0
  108. package/dist-esm/interfaces.js.map +1 -0
  109. package/dist-esm/metadata/buildApiExtractorConfig.js +51 -0
  110. package/dist-esm/metadata/buildApiExtractorConfig.js.map +1 -0
  111. package/dist-esm/metadata/buildESLintConfig.js +28 -0
  112. package/dist-esm/metadata/buildESLintConfig.js.map +1 -0
  113. package/dist-esm/metadata/buildLicenseFile.js +36 -0
  114. package/dist-esm/metadata/buildLicenseFile.js.map +1 -0
  115. package/dist-esm/metadata/buildPackageFile.js +234 -0
  116. package/dist-esm/metadata/buildPackageFile.js.map +1 -0
  117. package/dist-esm/metadata/buildReadmeFile.js +167 -0
  118. package/dist-esm/metadata/buildReadmeFile.js.map +1 -0
  119. package/dist-esm/metadata/buildRollupConfig.js +139 -0
  120. package/dist-esm/metadata/buildRollupConfig.js.map +1 -0
  121. package/dist-esm/metadata/buildTsConfig.js +67 -0
  122. package/dist-esm/metadata/buildTsConfig.js.map +1 -0
  123. package/dist-esm/package.json +1 -0
  124. package/dist-esm/static/paginateContent.js +211 -0
  125. package/dist-esm/static/paginateContent.js.map +1 -0
  126. package/dist-esm/static/pollingContent.js +75 -0
  127. package/dist-esm/static/pollingContent.js.map +1 -0
  128. package/dist-esm/test/buildEnvFile.js +24 -0
  129. package/dist-esm/test/buildEnvFile.js.map +1 -0
  130. package/dist-esm/test/buildKarmaConfig.js +14 -0
  131. package/dist-esm/test/buildKarmaConfig.js.map +1 -0
  132. package/dist-esm/test/buildRecordedClient.js +17 -0
  133. package/dist-esm/test/buildRecordedClient.js.map +1 -0
  134. package/dist-esm/test/buildSampleTest.js +14 -0
  135. package/dist-esm/test/buildSampleTest.js.map +1 -0
  136. package/dist-esm/test/template.js +189 -0
  137. package/dist-esm/test/template.js.map +1 -0
  138. package/package.json +40 -0
  139. package/publishPackage.js +11 -0
  140. package/rlc-common.build.log +2 -0
  141. package/src/buildClient.ts +251 -0
  142. package/src/buildClientDefinitions.ts +231 -0
  143. package/src/buildIndexFile.ts +172 -0
  144. package/src/buildIsUnexpectedHelper.ts +240 -0
  145. package/src/buildMethodShortcuts.ts +75 -0
  146. package/src/buildObjectTypes.ts +393 -0
  147. package/src/buildPaginateHelper.ts +33 -0
  148. package/src/buildParameterTypes.ts +435 -0
  149. package/src/buildPollingHelper.ts +18 -0
  150. package/src/buildResponseTypes.ts +169 -0
  151. package/src/buildSchemaType.ts +56 -0
  152. package/src/buildTopLevelIndexFile.ts +46 -0
  153. package/src/helpers/nameConstructors.ts +93 -0
  154. package/src/helpers/nameUtils.ts +227 -0
  155. package/src/helpers/operationHelpers.ts +103 -0
  156. package/src/helpers/schemaHelpers.ts +25 -0
  157. package/src/helpers/shortcutMethods.ts +60 -0
  158. package/src/index.ts +28 -0
  159. package/src/interfaces.ts +212 -0
  160. package/src/metadata/buildApiExtractorConfig.ts +59 -0
  161. package/src/metadata/buildESLintConfig.ts +34 -0
  162. package/src/metadata/buildLicenseFile.ts +39 -0
  163. package/src/metadata/buildPackageFile.ts +271 -0
  164. package/src/metadata/buildReadmeFile.ts +231 -0
  165. package/src/metadata/buildRollupConfig.ts +147 -0
  166. package/src/metadata/buildTsConfig.ts +79 -0
  167. package/src/static/paginateContent.ts +210 -0
  168. package/src/static/pollingContent.ts +74 -0
  169. package/src/test/buildEnvFile.ts +26 -0
  170. package/src/test/buildKarmaConfig.ts +15 -0
  171. package/src/test/buildRecordedClient.ts +18 -0
  172. package/src/test/buildSampleTest.ts +15 -0
  173. package/src/test/template.ts +192 -0
  174. package/tsconfig-cjs.json +9 -0
  175. package/tsconfig-common.json +13 -0
  176. package/tsconfig.json +13 -0
  177. package/types/buildClient.d.ts +2 -0
  178. package/types/buildClientDefinitions.d.ts +5 -0
  179. package/types/buildIndexFile.d.ts +5 -0
  180. package/types/buildIsUnexpectedHelper.d.ts +5 -0
  181. package/types/buildMethodShortcuts.d.ts +4 -0
  182. package/types/buildObjectTypes.d.ts +14 -0
  183. package/types/buildPaginateHelper.d.ts +5 -0
  184. package/types/buildParameterTypes.d.ts +5 -0
  185. package/types/buildPollingHelper.d.ts +5 -0
  186. package/types/buildResponseTypes.d.ts +5 -0
  187. package/types/buildSchemaType.d.ts +19 -0
  188. package/types/buildTopLevelIndexFile.d.ts +5 -0
  189. package/types/helpers/nameConstructors.d.ts +28 -0
  190. package/types/helpers/nameUtils.d.ts +25 -0
  191. package/types/helpers/operationHelpers.d.ts +9 -0
  192. package/types/helpers/schemaHelpers.d.ts +4 -0
  193. package/types/helpers/shortcutMethods.d.ts +3 -0
  194. package/types/index.d.ts +25 -0
  195. package/types/interfaces.d.ts +186 -0
  196. package/types/metadata/buildApiExtractorConfig.d.ts +5 -0
  197. package/types/metadata/buildESLintConfig.d.ts +5 -0
  198. package/types/metadata/buildLicenseFile.d.ts +5 -0
  199. package/types/metadata/buildPackageFile.d.ts +5 -0
  200. package/types/metadata/buildReadmeFile.d.ts +5 -0
  201. package/types/metadata/buildRollupConfig.d.ts +5 -0
  202. package/types/metadata/buildTsConfig.d.ts +5 -0
  203. package/types/static/paginateContent.d.ts +1 -0
  204. package/types/static/pollingContent.d.ts +1 -0
  205. package/types/test/buildEnvFile.d.ts +9 -0
  206. package/types/test/buildKarmaConfig.d.ts +5 -0
  207. package/types/test/buildRecordedClient.d.ts +5 -0
  208. package/types/test/buildSampleTest.d.ts +5 -0
  209. package/types/test/template.d.ts +5 -0
@@ -0,0 +1,435 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import {
5
+ InterfaceDeclarationStructure,
6
+ Project,
7
+ PropertySignatureStructure,
8
+ SourceFile,
9
+ StructureKind
10
+ } from "ts-morph";
11
+ import * as path from "path";
12
+ import {
13
+ ImportKind,
14
+ ParameterMetadata,
15
+ ParameterMetadatas,
16
+ RLCModel,
17
+ Schema
18
+ } from "./interfaces.js";
19
+ import { NameType, normalizeName } from "./helpers/nameUtils.js";
20
+ import {
21
+ getParameterBaseName,
22
+ getParameterTypeName
23
+ } from "./helpers/nameConstructors.js";
24
+
25
+ export function buildParameterTypes(model: RLCModel) {
26
+ const project = new Project();
27
+ const srcPath = model.srcPath;
28
+ const filePath = path.join(srcPath, `parameters.ts`);
29
+ const parametersFile = project.createSourceFile(filePath, undefined, {
30
+ overwrite: true
31
+ });
32
+ let hasHeaders = false;
33
+
34
+ if (!model.parameters) {
35
+ return;
36
+ }
37
+ for (const requestParameter of model.parameters) {
38
+ const baseParameterName = getParameterBaseName(
39
+ requestParameter.operationGroup,
40
+ requestParameter.operationName
41
+ );
42
+ const requestCount = requestParameter?.parameters?.length ?? 0;
43
+ const topParamName = getParameterTypeName(baseParameterName);
44
+ const subParamNames: string[] = [];
45
+
46
+ // We need to loop the requests. An operation with multiple requests means that
47
+ // the operation can get different values for content-type and each value may
48
+ // have a different type associated to it.
49
+ for (let i = 0; i < requestCount; i++) {
50
+ const parameter = requestParameter.parameters[i];
51
+ const internalReferences = new Set<string>();
52
+ // In case we have more than one request to model we need to add a suffix to differentiate
53
+ const nameSuffix = i > 0 ? `${i}` : "";
54
+ const parameterInterfaceName =
55
+ requestCount > 1
56
+ ? `${baseParameterName}RequestParameters${nameSuffix}`
57
+ : topParamName;
58
+ const queryParameterDefinitions = buildQueryParameterDefinition(
59
+ parameter,
60
+ baseParameterName,
61
+ internalReferences,
62
+ i
63
+ );
64
+ const pathParameterDefinitions = buildPathParameterDefinitions(
65
+ parameter,
66
+ baseParameterName,
67
+ parametersFile,
68
+ internalReferences,
69
+ i
70
+ );
71
+
72
+ const headerParameterDefinitions = buildHeaderParameterDefinitions(
73
+ parameter,
74
+ baseParameterName,
75
+ parametersFile,
76
+ internalReferences,
77
+ i
78
+ );
79
+
80
+ const contentTypeParameterDefinition =
81
+ buildContentTypeParametersDefinition(
82
+ parameter,
83
+ baseParameterName,
84
+ internalReferences,
85
+ i
86
+ );
87
+
88
+ const bodyParameterDefinition = buildBodyParametersDefinition(
89
+ parameter,
90
+ baseParameterName,
91
+ internalReferences,
92
+ i
93
+ );
94
+
95
+ // Add interfaces for body and query parameters
96
+ parametersFile.addInterfaces([
97
+ ...(bodyParameterDefinition ?? []),
98
+ ...(queryParameterDefinitions ?? []),
99
+ ...(pathParameterDefinitions ? [pathParameterDefinitions] : []),
100
+ ...(headerParameterDefinitions ? [headerParameterDefinitions] : []),
101
+ ...(contentTypeParameterDefinition
102
+ ? [contentTypeParameterDefinition]
103
+ : [])
104
+ ]);
105
+
106
+ // Add Operation parameters type alias which is composed of the types we generated above
107
+ // plus the common type RequestParameters
108
+ parametersFile.addTypeAlias({
109
+ name: parameterInterfaceName,
110
+ isExported: true,
111
+ type: [...internalReferences, "RequestParameters"].join(" & ")
112
+ });
113
+
114
+ subParamNames.push(parameterInterfaceName);
115
+
116
+ if (headerParameterDefinitions !== undefined) {
117
+ hasHeaders = true;
118
+ }
119
+ }
120
+ // Add Operation parameters type alias which is composed of the types we generated above
121
+ // plus the common type RequestParameters
122
+ if (requestCount > 1) {
123
+ parametersFile.addTypeAlias({
124
+ name: topParamName,
125
+ isExported: true,
126
+ type: [...subParamNames].join(" | ")
127
+ });
128
+ }
129
+ }
130
+
131
+ if (hasHeaders) {
132
+ parametersFile.addImportDeclarations([
133
+ {
134
+ namedImports: ["RawHttpHeadersInput"],
135
+ moduleSpecifier: "@azure/core-rest-pipeline"
136
+ }
137
+ ]);
138
+ }
139
+ parametersFile.addImportDeclarations([
140
+ {
141
+ namedImports: ["RequestParameters"],
142
+ moduleSpecifier: "@azure-rest/core-client"
143
+ }
144
+ ]);
145
+ if (model.importSet?.has(ImportKind.ParameterInput)) {
146
+ parametersFile.addImportDeclarations([
147
+ {
148
+ namedImports: [
149
+ ...Array.from(model.importSet?.get(ImportKind.ParameterInput) || [])
150
+ ],
151
+ moduleSpecifier: "./models"
152
+ }
153
+ ]);
154
+ }
155
+ return { path: filePath, content: parametersFile.getFullText() };
156
+ }
157
+
158
+ function buildQueryParameterDefinition(
159
+ parameters: ParameterMetadatas,
160
+ baseName: string,
161
+ internalReferences: Set<string>,
162
+ requestIndex: number
163
+ ): InterfaceDeclarationStructure[] | undefined {
164
+ const queryParameters = (parameters?.parameters || []).filter(
165
+ (p) => p.type === "query"
166
+ );
167
+
168
+ if (!queryParameters.length) {
169
+ return undefined;
170
+ }
171
+
172
+ const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
173
+ const queryParameterInterfaceName = `${baseName}QueryParam${nameSuffix}`;
174
+ const queryParameterPropertiesName = `${baseName}QueryParamProperties`;
175
+
176
+ // Get the property signature for each query parameter
177
+ const propertiesDefinition = queryParameters.map((qp) =>
178
+ getPropertyFromSchema(qp.param)
179
+ );
180
+
181
+ const hasRequiredParameters = propertiesDefinition.some(
182
+ (p) => !p.hasQuestionToken
183
+ );
184
+
185
+ const propertiesInterface: InterfaceDeclarationStructure = {
186
+ kind: StructureKind.Interface,
187
+ isExported: true,
188
+ name: queryParameterPropertiesName,
189
+ properties: propertiesDefinition
190
+ };
191
+
192
+ const parameterInterface: InterfaceDeclarationStructure = {
193
+ kind: StructureKind.Interface,
194
+ isExported: true,
195
+ name: queryParameterInterfaceName,
196
+ properties: [
197
+ {
198
+ name: "queryParameters",
199
+ type: queryParameterPropertiesName,
200
+ // Mark as optional if there are no required parameters
201
+ hasQuestionToken: !hasRequiredParameters
202
+ }
203
+ ]
204
+ };
205
+
206
+ // Mark the queryParameter interface for importing
207
+ internalReferences.add(queryParameterInterfaceName);
208
+
209
+ return [propertiesInterface, parameterInterface];
210
+ }
211
+
212
+ function getPropertyFromSchema(schema: Schema): PropertySignatureStructure {
213
+ const description = schema.description;
214
+ return {
215
+ name: schema.name,
216
+ ...(description && { docs: [{ description }] }),
217
+ type: schema.type,
218
+ hasQuestionToken: !Boolean(schema.required),
219
+ kind: StructureKind.PropertySignature
220
+ };
221
+ }
222
+
223
+ function buildPathParameterDefinitions(
224
+ parameters: ParameterMetadatas,
225
+ baseName: string,
226
+ parametersFile: SourceFile,
227
+ internalReferences: Set<string>,
228
+ requestIndex: number
229
+ ): InterfaceDeclarationStructure | undefined {
230
+ const pathParameters = (parameters.parameters || []).filter(
231
+ (p) => p.type === "path"
232
+ );
233
+ if (!pathParameters.length) {
234
+ return undefined;
235
+ }
236
+
237
+ const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
238
+ const pathParameterInterfaceName = `${baseName}PathParam${nameSuffix}`;
239
+
240
+ const pathInterface = getPathInterfaceDefinition(pathParameters, baseName);
241
+
242
+ if (pathInterface) {
243
+ parametersFile.addInterface(pathInterface);
244
+ }
245
+
246
+ internalReferences.add(pathParameterInterfaceName);
247
+
248
+ return {
249
+ isExported: true,
250
+ kind: StructureKind.Interface,
251
+ name: pathParameterInterfaceName,
252
+ properties: [
253
+ {
254
+ name: "pathParameters",
255
+ type: `${baseName}PathParameters`,
256
+ kind: StructureKind.PropertySignature
257
+ }
258
+ ]
259
+ };
260
+ }
261
+
262
+ function getPathInterfaceDefinition(
263
+ pathParameters: ParameterMetadata[],
264
+ baseName: string
265
+ ): undefined | InterfaceDeclarationStructure {
266
+ const pathInterfaceName = `${baseName}PathParameters`;
267
+ return {
268
+ kind: StructureKind.Interface,
269
+ isExported: true,
270
+ name: pathInterfaceName,
271
+ properties: pathParameters.map((p: ParameterMetadata) =>
272
+ getPropertyFromSchema(p.param)
273
+ )
274
+ };
275
+ }
276
+
277
+ function buildHeaderParameterDefinitions(
278
+ parameters: ParameterMetadatas,
279
+ baseName: string,
280
+ parametersFile: SourceFile,
281
+ internalReferences: Set<string>,
282
+ requestIndex: number
283
+ ): InterfaceDeclarationStructure | undefined {
284
+ const headerParameters = (parameters.parameters || []).filter(
285
+ (p) => p.type === "header" && p.name !== "contentType"
286
+ );
287
+ if (!headerParameters.length) {
288
+ return undefined;
289
+ }
290
+
291
+ const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
292
+ const headerParameterInterfaceName = `${baseName}HeaderParam${nameSuffix}`;
293
+
294
+ const headersInterface = getRequestHeaderInterfaceDefinition(
295
+ headerParameters,
296
+ baseName
297
+ );
298
+
299
+ if (headersInterface) {
300
+ parametersFile.addInterface(headersInterface);
301
+ }
302
+
303
+ internalReferences.add(headerParameterInterfaceName);
304
+
305
+ return {
306
+ isExported: true,
307
+ kind: StructureKind.Interface,
308
+ name: headerParameterInterfaceName,
309
+ properties: [
310
+ {
311
+ name: "headers",
312
+ type: `RawHttpHeadersInput & ${baseName}Headers`,
313
+ kind: StructureKind.PropertySignature
314
+ }
315
+ ]
316
+ };
317
+ }
318
+
319
+ function getRequestHeaderInterfaceDefinition(
320
+ headerParameters: ParameterMetadata[],
321
+ baseName: string
322
+ ): undefined | InterfaceDeclarationStructure {
323
+ const headersInterfaceName = `${baseName}Headers`;
324
+ return {
325
+ kind: StructureKind.Interface,
326
+ isExported: true,
327
+ name: headersInterfaceName,
328
+ properties: headerParameters.map((h: ParameterMetadata) =>
329
+ getPropertyFromSchema(h.param)
330
+ )
331
+ };
332
+ }
333
+
334
+ function buildContentTypeParametersDefinition(
335
+ parameters: ParameterMetadatas,
336
+ baseName: string,
337
+ internalReferences: Set<string>,
338
+ requestIndex: number
339
+ ): InterfaceDeclarationStructure | undefined {
340
+ const mediaTypeParameters = (parameters.parameters || []).filter(
341
+ (p) => p.type === "header" && p.name === "contentType"
342
+ );
343
+ if (!mediaTypeParameters.length) {
344
+ return undefined;
345
+ }
346
+
347
+ const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
348
+ const mediaTypesParameterInterfaceName = `${baseName}MediaTypesParam${nameSuffix}`;
349
+
350
+ // Mark the queryParameter interface for importing
351
+ internalReferences.add(mediaTypesParameterInterfaceName);
352
+ const mediaParam = mediaTypeParameters[0].param;
353
+
354
+ return {
355
+ isExported: true,
356
+ kind: StructureKind.Interface,
357
+ name: mediaTypesParameterInterfaceName,
358
+ properties: [getPropertyFromSchema(mediaParam)]
359
+ };
360
+ }
361
+
362
+ function buildBodyParametersDefinition(
363
+ parameters: ParameterMetadatas,
364
+ baseName: string,
365
+ internalReferences: Set<string>,
366
+ requestIndex: number
367
+ ): InterfaceDeclarationStructure[] {
368
+ const bodyParameters = parameters.body;
369
+ if (
370
+ !bodyParameters ||
371
+ !bodyParameters?.body ||
372
+ !bodyParameters?.body.length
373
+ ) {
374
+ return [];
375
+ }
376
+
377
+ const nameSuffix = requestIndex > 0 ? `${requestIndex}` : "";
378
+ const bodyParameterInterfaceName = `${baseName}BodyParam${nameSuffix}`;
379
+ internalReferences.add(bodyParameterInterfaceName);
380
+
381
+ // In case of formData we'd get multiple properties in body marked as partialBody
382
+ if (bodyParameters.isPartialBody) {
383
+ let allOptionalParts = true;
384
+ const propertiesDefinitions: PropertySignatureStructure[] = [];
385
+ for (const param of bodyParameters.body) {
386
+ if (param.required) {
387
+ allOptionalParts = false;
388
+ }
389
+
390
+ propertiesDefinitions.push(getPropertyFromSchema(param));
391
+ }
392
+
393
+ const formBodyName = `${baseName}FormBody`;
394
+ const formBodyInterface: InterfaceDeclarationStructure = {
395
+ isExported: true,
396
+ kind: StructureKind.Interface,
397
+ name: formBodyName,
398
+ properties: propertiesDefinitions
399
+ };
400
+
401
+ return [
402
+ {
403
+ isExported: true,
404
+ kind: StructureKind.Interface,
405
+ name: bodyParameterInterfaceName,
406
+ properties: [
407
+ {
408
+ name: "body",
409
+ type: formBodyName,
410
+ hasQuestionToken: allOptionalParts
411
+ }
412
+ ]
413
+ },
414
+ formBodyInterface
415
+ ];
416
+ } else {
417
+ const bodySignature = getPropertyFromSchema(bodyParameters.body[0]);
418
+
419
+ return [
420
+ {
421
+ isExported: true,
422
+ kind: StructureKind.Interface,
423
+ name: bodyParameterInterfaceName,
424
+ properties: [
425
+ {
426
+ docs: bodySignature.docs,
427
+ name: "body",
428
+ type: bodySignature.type,
429
+ hasQuestionToken: bodySignature.hasQuestionToken
430
+ }
431
+ ]
432
+ }
433
+ ];
434
+ }
435
+ }
@@ -0,0 +1,18 @@
1
+ import { RLCModel } from "./interfaces.js";
2
+ import * as path from "path";
3
+ // @ts-ignore: to fix the handlebars issue
4
+ import hbs from "handlebars";
5
+ import { hasPollingOperations } from "./helpers/operationHelpers.js";
6
+ import { pollingContent } from "./static/pollingContent.js";
7
+
8
+ export function buildPollingHelper(model: RLCModel) {
9
+ if (!hasPollingOperations(model)) {
10
+ return;
11
+ }
12
+ const readmeFileContents = hbs.compile(pollingContent, { noEscape: true });
13
+ const { srcPath } = model;
14
+ return {
15
+ path: path.join(srcPath, "pollingHelper.ts"),
16
+ content: readmeFileContents({})
17
+ };
18
+ }
@@ -0,0 +1,169 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import {
5
+ InterfaceDeclarationStructure,
6
+ OptionalKind,
7
+ Project,
8
+ PropertySignatureStructure,
9
+ StructureKind
10
+ } from "ts-morph";
11
+ import {
12
+ ImportKind,
13
+ ResponseHeaderSchema,
14
+ ResponseMetadata,
15
+ RLCModel
16
+ } from "./interfaces.js";
17
+ import * as path from "path";
18
+ import {
19
+ getResponseBaseName,
20
+ getResponseTypeName
21
+ } from "./helpers/nameConstructors.js";
22
+
23
+ export function buildResponseTypes(model: RLCModel) {
24
+ const project = new Project();
25
+ const srcPath = model.srcPath;
26
+ const filePath = path.join(srcPath, `responses.ts`);
27
+ const responsesFile = project.createSourceFile(filePath, undefined, {
28
+ overwrite: true
29
+ });
30
+ // Set used to track down which models need to be imported
31
+ // Track if we need to import RawHttpHeaders
32
+ let hasHeaders = false;
33
+ if (!model.responses) {
34
+ return;
35
+ }
36
+ for (const operationResponse of model.responses) {
37
+ for (const response of operationResponse.responses) {
38
+ // Building the response type base name
39
+ const baseResponseName = getResponseBaseName(
40
+ operationResponse.operationGroup,
41
+ operationResponse.operationName,
42
+ response.statusCode
43
+ );
44
+
45
+ // Build the response header
46
+ const headersInterface: InterfaceDeclarationStructure | undefined =
47
+ getResponseHeaderInterfaceDefinition(response, baseResponseName);
48
+ if (headersInterface) {
49
+ hasHeaders = true;
50
+ responsesFile.addInterface(headersInterface);
51
+ }
52
+
53
+ // Get the information to build the Response Interface
54
+ const responseTypeName = getResponseTypeName(baseResponseName);
55
+ const responseProperties = getResponseInterfaceProperties(
56
+ response,
57
+ headersInterface?.name
58
+ );
59
+
60
+ const responseInterfaceDefinition: OptionalKind<InterfaceDeclarationStructure> =
61
+ {
62
+ name: responseTypeName,
63
+ properties: responseProperties,
64
+ isExported: true,
65
+ extends: ["HttpResponse"]
66
+ };
67
+
68
+ // Only add a description if one was provided in the Swagger
69
+ // otherwise skip to avoid having empty TSDoc lines
70
+ if (response.description) {
71
+ responseInterfaceDefinition.docs = [
72
+ { description: response.description }
73
+ ];
74
+ }
75
+
76
+ // Add the response interface to the responses file
77
+ responsesFile.addInterface(responseInterfaceDefinition);
78
+ }
79
+ }
80
+
81
+ if (hasHeaders) {
82
+ responsesFile.addImportDeclarations([
83
+ {
84
+ namedImports: ["RawHttpHeaders"],
85
+ moduleSpecifier: "@azure/core-rest-pipeline"
86
+ }
87
+ ]);
88
+ }
89
+ responsesFile.addImportDeclarations([
90
+ {
91
+ namedImports: ["HttpResponse"],
92
+ moduleSpecifier: "@azure-rest/core-client"
93
+ }
94
+ ]);
95
+
96
+ if (model.importSet?.has(ImportKind.ResponseOutput)) {
97
+ responsesFile.addImportDeclarations([
98
+ {
99
+ namedImports: [
100
+ ...Array.from(model.importSet.get(ImportKind.ResponseOutput) || [])
101
+ ],
102
+ moduleSpecifier: "./outputModels"
103
+ }
104
+ ]);
105
+ }
106
+ return { path: filePath, content: responsesFile.getFullText() };
107
+ }
108
+
109
+ function getResponseHeaderInterfaceDefinition(
110
+ response: ResponseMetadata,
111
+ baseName: string
112
+ ): undefined | InterfaceDeclarationStructure {
113
+ // Check if there are any required headers
114
+ if (!response.headers) {
115
+ return;
116
+ }
117
+ const headersInterfaceName = `${baseName}Headers`;
118
+ return {
119
+ kind: StructureKind.Interface,
120
+ isExported: true,
121
+ name: headersInterfaceName,
122
+ properties: response?.headers.map((h: ResponseHeaderSchema) => {
123
+ const description = h.description;
124
+ return {
125
+ name: h.name,
126
+ ...(description && { docs: [{ description }] }),
127
+ type: h.type,
128
+ hasQuestionToken: !Boolean(h.required)
129
+ };
130
+ })
131
+ };
132
+ }
133
+
134
+ /**
135
+ * Gets the properties that need to be part of the response interface
136
+ */
137
+ function getResponseInterfaceProperties(
138
+ response: ResponseMetadata,
139
+ headersInterfaceName?: string
140
+ ) {
141
+ const statusCode = response.statusCode;
142
+ const responseProperties: PropertySignatureStructure[] = [
143
+ {
144
+ name: "status",
145
+ type: statusCode === "default" ? `string` : `"${statusCode}"`,
146
+ kind: StructureKind.PropertySignature
147
+ }
148
+ ];
149
+
150
+ if (response.body) {
151
+ const description = response.body.description;
152
+ responseProperties.push({
153
+ name: "body",
154
+ type: response.body.type,
155
+ kind: StructureKind.PropertySignature,
156
+ ...(description && { docs: [{ description }] })
157
+ });
158
+ }
159
+
160
+ if (headersInterfaceName) {
161
+ responseProperties.push({
162
+ name: "headers",
163
+ type: `RawHttpHeaders & ${headersInterfaceName}`,
164
+ kind: StructureKind.PropertySignature
165
+ });
166
+ }
167
+
168
+ return responseProperties;
169
+ }
@@ -0,0 +1,56 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import { Project } from "ts-morph";
5
+ import * as path from "path";
6
+ import {
7
+ buildObjectInterfaces,
8
+ buildPolymorphicAliases
9
+ } from "./buildObjectTypes.js";
10
+ import { RLCModel, SchemaContext } from "./interfaces.js";
11
+
12
+ /**
13
+ * Generates types to represent schema definitions in the swagger
14
+ */
15
+ export function buildSchemaTypes(model: RLCModel) {
16
+ const { srcPath } = model;
17
+ const project = new Project();
18
+ let filePath = path.join(srcPath, `models.ts`);
19
+ const inputModelFile = generateModelFiles(model, project, filePath, [
20
+ SchemaContext.Input
21
+ ]);
22
+ filePath = path.join(srcPath, `outputModels.ts`);
23
+ const outputModelFile = generateModelFiles(model, project, filePath, [
24
+ SchemaContext.Output,
25
+ SchemaContext.Exception
26
+ ]);
27
+ return { inputModelFile, outputModelFile };
28
+ }
29
+
30
+ export function generateModelFiles(
31
+ model: RLCModel,
32
+ project: Project,
33
+ filePath: string,
34
+ schemaContext: SchemaContext[]
35
+ ) {
36
+ // Track models that need to be imported
37
+ const importedModels = new Set<string>();
38
+
39
+ const objectsDefinitions = buildObjectInterfaces(
40
+ model,
41
+ importedModels,
42
+ schemaContext
43
+ );
44
+ const objectTypeAliases = buildPolymorphicAliases(model, schemaContext);
45
+
46
+ if (objectTypeAliases.length || objectsDefinitions.length) {
47
+ const modelsFile = project.createSourceFile(filePath, undefined, {
48
+ overwrite: true
49
+ });
50
+
51
+ modelsFile.addInterfaces(objectsDefinitions);
52
+ modelsFile.addTypeAliases(objectTypeAliases);
53
+ return { path: filePath, content: modelsFile.getFullText() };
54
+ }
55
+ return undefined;
56
+ }