@azure-tools/rlc-common 0.11.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 (232) hide show
  1. package/.eslintrc.json +23 -0
  2. package/.prettierignore +1 -0
  3. package/.prettierrc +7 -0
  4. package/.rush/temp/package-deps_build.json +53 -0
  5. package/.rush/temp/shrinkwrap-deps.json +147 -0
  6. package/CHANGELOG.md +61 -0
  7. package/CONTRIBUTING.md +30 -0
  8. package/README.md +3 -0
  9. package/dist/buildClient.js +268 -0
  10. package/dist/buildClient.js.map +1 -0
  11. package/dist/buildClientDefinitions.js +160 -0
  12. package/dist/buildClientDefinitions.js.map +1 -0
  13. package/dist/buildIndexFile.js +170 -0
  14. package/dist/buildIndexFile.js.map +1 -0
  15. package/dist/buildIsUnexpectedHelper.js +220 -0
  16. package/dist/buildIsUnexpectedHelper.js.map +1 -0
  17. package/dist/buildMethodShortcuts.js +50 -0
  18. package/dist/buildMethodShortcuts.js.map +1 -0
  19. package/dist/buildObjectTypes.js +286 -0
  20. package/dist/buildObjectTypes.js.map +1 -0
  21. package/dist/buildPaginateHelper.js +30 -0
  22. package/dist/buildPaginateHelper.js.map +1 -0
  23. package/dist/buildParameterTypes.js +315 -0
  24. package/dist/buildParameterTypes.js.map +1 -0
  25. package/dist/buildPollingHelper.js +21 -0
  26. package/dist/buildPollingHelper.js.map +1 -0
  27. package/dist/buildResponseTypes.js +135 -0
  28. package/dist/buildResponseTypes.js.map +1 -0
  29. package/dist/buildSchemaType.js +65 -0
  30. package/dist/buildSchemaType.js.map +1 -0
  31. package/dist/buildSerializeHelper.js +35 -0
  32. package/dist/buildSerializeHelper.js.map +1 -0
  33. package/dist/buildTopLevelIndexFile.js +48 -0
  34. package/dist/buildTopLevelIndexFile.js.map +1 -0
  35. package/dist/helpers/nameConstructors.js +41 -0
  36. package/dist/helpers/nameConstructors.js.map +1 -0
  37. package/dist/helpers/nameUtils.js +196 -0
  38. package/dist/helpers/nameUtils.js.map +1 -0
  39. package/dist/helpers/operationHelpers.js +103 -0
  40. package/dist/helpers/operationHelpers.js.map +1 -0
  41. package/dist/helpers/pathUtils.js +13 -0
  42. package/dist/helpers/pathUtils.js.map +1 -0
  43. package/dist/helpers/schemaHelpers.js +27 -0
  44. package/dist/helpers/schemaHelpers.js.map +1 -0
  45. package/dist/helpers/shortcutMethods.js +46 -0
  46. package/dist/helpers/shortcutMethods.js.map +1 -0
  47. package/dist/index.js +45 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/interfaces.js +18 -0
  50. package/dist/interfaces.js.map +1 -0
  51. package/dist/metadata/buildApiExtractorConfig.js +56 -0
  52. package/dist/metadata/buildApiExtractorConfig.js.map +1 -0
  53. package/dist/metadata/buildESLintConfig.js +33 -0
  54. package/dist/metadata/buildESLintConfig.js.map +1 -0
  55. package/dist/metadata/buildLicenseFile.js +41 -0
  56. package/dist/metadata/buildLicenseFile.js.map +1 -0
  57. package/dist/metadata/buildPackageFile.js +274 -0
  58. package/dist/metadata/buildPackageFile.js.map +1 -0
  59. package/dist/metadata/buildReadmeFile.js +170 -0
  60. package/dist/metadata/buildReadmeFile.js.map +1 -0
  61. package/dist/metadata/buildRollupConfig.js +144 -0
  62. package/dist/metadata/buildRollupConfig.js.map +1 -0
  63. package/dist/metadata/buildTsConfig.js +72 -0
  64. package/dist/metadata/buildTsConfig.js.map +1 -0
  65. package/dist/package.json +1 -0
  66. package/dist/static/paginateContent.js +214 -0
  67. package/dist/static/paginateContent.js.map +1 -0
  68. package/dist/static/pollingContent.js +98 -0
  69. package/dist/static/pollingContent.js.map +1 -0
  70. package/dist/static/serializeHelper.js +30 -0
  71. package/dist/static/serializeHelper.js.map +1 -0
  72. package/dist/test/buildEnvFile.js +31 -0
  73. package/dist/test/buildEnvFile.js.map +1 -0
  74. package/dist/test/buildKarmaConfig.js +19 -0
  75. package/dist/test/buildKarmaConfig.js.map +1 -0
  76. package/dist/test/buildRecordedClient.js +22 -0
  77. package/dist/test/buildRecordedClient.js.map +1 -0
  78. package/dist/test/buildSampleTest.js +19 -0
  79. package/dist/test/buildSampleTest.js.map +1 -0
  80. package/dist/test/template.js +191 -0
  81. package/dist/test/template.js.map +1 -0
  82. package/dist-esm/buildClient.js +261 -0
  83. package/dist-esm/buildClient.js.map +1 -0
  84. package/dist-esm/buildClientDefinitions.js +155 -0
  85. package/dist-esm/buildClientDefinitions.js.map +1 -0
  86. package/dist-esm/buildIndexFile.js +165 -0
  87. package/dist-esm/buildIndexFile.js.map +1 -0
  88. package/dist-esm/buildIsUnexpectedHelper.js +216 -0
  89. package/dist-esm/buildIsUnexpectedHelper.js.map +1 -0
  90. package/dist-esm/buildMethodShortcuts.js +46 -0
  91. package/dist-esm/buildMethodShortcuts.js.map +1 -0
  92. package/dist-esm/buildObjectTypes.js +288 -0
  93. package/dist-esm/buildObjectTypes.js.map +1 -0
  94. package/dist-esm/buildPaginateHelper.js +26 -0
  95. package/dist-esm/buildPaginateHelper.js.map +1 -0
  96. package/dist-esm/buildParameterTypes.js +321 -0
  97. package/dist-esm/buildParameterTypes.js.map +1 -0
  98. package/dist-esm/buildPollingHelper.js +17 -0
  99. package/dist-esm/buildPollingHelper.js.map +1 -0
  100. package/dist-esm/buildResponseTypes.js +140 -0
  101. package/dist-esm/buildResponseTypes.js.map +1 -0
  102. package/dist-esm/buildSchemaType.js +60 -0
  103. package/dist-esm/buildSchemaType.js.map +1 -0
  104. package/dist-esm/buildSerializeHelper.js +31 -0
  105. package/dist-esm/buildSerializeHelper.js.map +1 -0
  106. package/dist-esm/buildTopLevelIndexFile.js +44 -0
  107. package/dist-esm/buildTopLevelIndexFile.js.map +1 -0
  108. package/dist-esm/helpers/nameConstructors.js +34 -0
  109. package/dist-esm/helpers/nameConstructors.js.map +1 -0
  110. package/dist-esm/helpers/nameUtils.js +187 -0
  111. package/dist-esm/helpers/nameUtils.js.map +1 -0
  112. package/dist-esm/helpers/operationHelpers.js +84 -0
  113. package/dist-esm/helpers/operationHelpers.js.map +1 -0
  114. package/dist-esm/helpers/pathUtils.js +9 -0
  115. package/dist-esm/helpers/pathUtils.js.map +1 -0
  116. package/dist-esm/helpers/schemaHelpers.js +21 -0
  117. package/dist-esm/helpers/schemaHelpers.js.map +1 -0
  118. package/dist-esm/helpers/shortcutMethods.js +42 -0
  119. package/dist-esm/helpers/shortcutMethods.js.map +1 -0
  120. package/dist-esm/index.js +29 -0
  121. package/dist-esm/index.js.map +1 -0
  122. package/dist-esm/interfaces.js +15 -0
  123. package/dist-esm/interfaces.js.map +1 -0
  124. package/dist-esm/metadata/buildApiExtractorConfig.js +51 -0
  125. package/dist-esm/metadata/buildApiExtractorConfig.js.map +1 -0
  126. package/dist-esm/metadata/buildESLintConfig.js +28 -0
  127. package/dist-esm/metadata/buildESLintConfig.js.map +1 -0
  128. package/dist-esm/metadata/buildLicenseFile.js +36 -0
  129. package/dist-esm/metadata/buildLicenseFile.js.map +1 -0
  130. package/dist-esm/metadata/buildPackageFile.js +276 -0
  131. package/dist-esm/metadata/buildPackageFile.js.map +1 -0
  132. package/dist-esm/metadata/buildReadmeFile.js +167 -0
  133. package/dist-esm/metadata/buildReadmeFile.js.map +1 -0
  134. package/dist-esm/metadata/buildRollupConfig.js +139 -0
  135. package/dist-esm/metadata/buildRollupConfig.js.map +1 -0
  136. package/dist-esm/metadata/buildTsConfig.js +67 -0
  137. package/dist-esm/metadata/buildTsConfig.js.map +1 -0
  138. package/dist-esm/package.json +1 -0
  139. package/dist-esm/static/paginateContent.js +211 -0
  140. package/dist-esm/static/paginateContent.js.map +1 -0
  141. package/dist-esm/static/pollingContent.js +95 -0
  142. package/dist-esm/static/pollingContent.js.map +1 -0
  143. package/dist-esm/static/serializeHelper.js +27 -0
  144. package/dist-esm/static/serializeHelper.js.map +1 -0
  145. package/dist-esm/test/buildEnvFile.js +24 -0
  146. package/dist-esm/test/buildEnvFile.js.map +1 -0
  147. package/dist-esm/test/buildKarmaConfig.js +14 -0
  148. package/dist-esm/test/buildKarmaConfig.js.map +1 -0
  149. package/dist-esm/test/buildRecordedClient.js +17 -0
  150. package/dist-esm/test/buildRecordedClient.js.map +1 -0
  151. package/dist-esm/test/buildSampleTest.js +14 -0
  152. package/dist-esm/test/buildSampleTest.js.map +1 -0
  153. package/dist-esm/test/template.js +188 -0
  154. package/dist-esm/test/template.js.map +1 -0
  155. package/package.json +46 -0
  156. package/publishPackage.js +11 -0
  157. package/rlc-common.build.log +2 -0
  158. package/src/buildClient.ts +353 -0
  159. package/src/buildClientDefinitions.ts +235 -0
  160. package/src/buildIndexFile.ts +202 -0
  161. package/src/buildIsUnexpectedHelper.ts +240 -0
  162. package/src/buildMethodShortcuts.ts +75 -0
  163. package/src/buildObjectTypes.ts +449 -0
  164. package/src/buildPaginateHelper.ts +33 -0
  165. package/src/buildParameterTypes.ts +477 -0
  166. package/src/buildPollingHelper.ts +18 -0
  167. package/src/buildResponseTypes.ts +186 -0
  168. package/src/buildSchemaType.ts +85 -0
  169. package/src/buildSerializeHelper.ts +42 -0
  170. package/src/buildTopLevelIndexFile.ts +52 -0
  171. package/src/helpers/nameConstructors.ts +93 -0
  172. package/src/helpers/nameUtils.ts +227 -0
  173. package/src/helpers/operationHelpers.ts +119 -0
  174. package/src/helpers/pathUtils.ts +9 -0
  175. package/src/helpers/schemaHelpers.ts +25 -0
  176. package/src/helpers/shortcutMethods.ts +60 -0
  177. package/src/index.ts +29 -0
  178. package/src/interfaces.ts +227 -0
  179. package/src/metadata/buildApiExtractorConfig.ts +59 -0
  180. package/src/metadata/buildESLintConfig.ts +34 -0
  181. package/src/metadata/buildLicenseFile.ts +39 -0
  182. package/src/metadata/buildPackageFile.ts +334 -0
  183. package/src/metadata/buildReadmeFile.ts +231 -0
  184. package/src/metadata/buildRollupConfig.ts +147 -0
  185. package/src/metadata/buildTsConfig.ts +79 -0
  186. package/src/static/paginateContent.ts +210 -0
  187. package/src/static/pollingContent.ts +94 -0
  188. package/src/static/serializeHelper.ts +29 -0
  189. package/src/test/buildEnvFile.ts +26 -0
  190. package/src/test/buildKarmaConfig.ts +15 -0
  191. package/src/test/buildRecordedClient.ts +18 -0
  192. package/src/test/buildSampleTest.ts +15 -0
  193. package/src/test/template.ts +191 -0
  194. package/tsconfig-cjs.json +9 -0
  195. package/tsconfig-common.json +13 -0
  196. package/tsconfig.json +13 -0
  197. package/types/buildClient.d.ts +2 -0
  198. package/types/buildClientDefinitions.d.ts +5 -0
  199. package/types/buildIndexFile.d.ts +5 -0
  200. package/types/buildIsUnexpectedHelper.d.ts +5 -0
  201. package/types/buildMethodShortcuts.d.ts +4 -0
  202. package/types/buildObjectTypes.d.ts +15 -0
  203. package/types/buildPaginateHelper.d.ts +5 -0
  204. package/types/buildParameterTypes.d.ts +13 -0
  205. package/types/buildPollingHelper.d.ts +5 -0
  206. package/types/buildResponseTypes.d.ts +5 -0
  207. package/types/buildSchemaType.d.ts +19 -0
  208. package/types/buildSerializeHelper.d.ts +5 -0
  209. package/types/buildTopLevelIndexFile.d.ts +5 -0
  210. package/types/helpers/nameConstructors.d.ts +28 -0
  211. package/types/helpers/nameUtils.d.ts +25 -0
  212. package/types/helpers/operationHelpers.d.ts +13 -0
  213. package/types/helpers/pathUtils.d.ts +1 -0
  214. package/types/helpers/schemaHelpers.d.ts +4 -0
  215. package/types/helpers/shortcutMethods.d.ts +3 -0
  216. package/types/index.d.ts +26 -0
  217. package/types/interfaces.d.ts +200 -0
  218. package/types/metadata/buildApiExtractorConfig.d.ts +5 -0
  219. package/types/metadata/buildESLintConfig.d.ts +5 -0
  220. package/types/metadata/buildLicenseFile.d.ts +5 -0
  221. package/types/metadata/buildPackageFile.d.ts +5 -0
  222. package/types/metadata/buildReadmeFile.d.ts +5 -0
  223. package/types/metadata/buildRollupConfig.d.ts +5 -0
  224. package/types/metadata/buildTsConfig.d.ts +5 -0
  225. package/types/static/paginateContent.d.ts +1 -0
  226. package/types/static/pollingContent.d.ts +1 -0
  227. package/types/static/serializeHelper.d.ts +4 -0
  228. package/types/test/buildEnvFile.d.ts +9 -0
  229. package/types/test/buildKarmaConfig.d.ts +5 -0
  230. package/types/test/buildRecordedClient.d.ts +5 -0
  231. package/types/test/buildSampleTest.d.ts +5 -0
  232. package/types/test/template.d.ts +5 -0
@@ -0,0 +1,85 @@
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
+ buildObjectAliases,
8
+ buildObjectInterfaces,
9
+ buildPolymorphicAliases
10
+ } from "./buildObjectTypes.js";
11
+ import { RLCModel, SchemaContext } from "./interfaces.js";
12
+
13
+ /**
14
+ * Generates types to represent schema definitions in the swagger
15
+ */
16
+ export function buildSchemaTypes(model: RLCModel) {
17
+ const { srcPath } = model;
18
+ const project = new Project();
19
+ let filePath = path.join(srcPath, `models.ts`);
20
+ const inputModelFile = generateModelFiles(model, project, filePath, [
21
+ SchemaContext.Input
22
+ ]);
23
+ filePath = path.join(srcPath, `outputModels.ts`);
24
+ const outputModelFile = generateModelFiles(model, project, filePath, [
25
+ SchemaContext.Output,
26
+ SchemaContext.Exception
27
+ ]);
28
+ return { inputModelFile, outputModelFile };
29
+ }
30
+
31
+ export function generateModelFiles(
32
+ model: RLCModel,
33
+ project: Project,
34
+ filePath: string,
35
+ schemaContext: SchemaContext[]
36
+ ) {
37
+ // Track models that need to be imported
38
+ const importedModels = new Set<string>();
39
+
40
+ const objectsDefinitions = buildObjectInterfaces(
41
+ model,
42
+ importedModels,
43
+ schemaContext
44
+ );
45
+
46
+ const objectTypeAliases = buildPolymorphicAliases(model, schemaContext);
47
+
48
+ const objectAliases = buildObjectAliases(
49
+ model,
50
+ importedModels,
51
+ schemaContext
52
+ );
53
+ if (
54
+ objectTypeAliases.length ||
55
+ objectsDefinitions.length ||
56
+ objectAliases.length
57
+ ) {
58
+ const modelsFile = project.createSourceFile(filePath, undefined, {
59
+ overwrite: true
60
+ });
61
+
62
+ modelsFile.addInterfaces(objectsDefinitions);
63
+ modelsFile.addTypeAliases(objectTypeAliases);
64
+ modelsFile.addTypeAliases(objectAliases);
65
+ if (importedModels.has("Paged")) {
66
+ modelsFile.addImportDeclarations([
67
+ {
68
+ namedImports: ["Paged"],
69
+ moduleSpecifier: "@azure/core-paging"
70
+ }
71
+ ]);
72
+ importedModels.delete("Paged");
73
+ }
74
+ if (importedModels.size > 0) {
75
+ modelsFile.addImportDeclarations([
76
+ {
77
+ namedImports: [...Array.from(importedModels || [])],
78
+ moduleSpecifier: "@azure-rest/core-client"
79
+ }
80
+ ]);
81
+ }
82
+ return { path: filePath, content: modelsFile.getFullText() };
83
+ }
84
+ return undefined;
85
+ }
@@ -0,0 +1,42 @@
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 {
6
+ hasMultiCollection,
7
+ hasPipeCollection,
8
+ hasSsvCollection,
9
+ hasTsvCollection
10
+ } from "./helpers/operationHelpers.js";
11
+ import {
12
+ buildMultiCollectionContent,
13
+ buildPipeCollectionContent,
14
+ buildSsvCollectionContent,
15
+ buildTsvCollectionContent
16
+ } from "./static/serializeHelper.js";
17
+
18
+ export function buildSerializeHelper(model: RLCModel) {
19
+ let serializeHelperContent = "";
20
+ if (hasMultiCollection(model)) {
21
+ serializeHelperContent += "\n" + buildMultiCollectionContent;
22
+ }
23
+ if (hasPipeCollection(model)) {
24
+ serializeHelperContent += "\n" + buildPipeCollectionContent;
25
+ }
26
+ if (hasSsvCollection(model)) {
27
+ serializeHelperContent += "\n" + buildSsvCollectionContent;
28
+ }
29
+ if (hasTsvCollection(model)) {
30
+ serializeHelperContent += "\n" + buildTsvCollectionContent;
31
+ }
32
+ if (serializeHelperContent !== "") {
33
+ const readmeFileContents = hbs.compile(serializeHelperContent, {
34
+ noEscape: true
35
+ });
36
+ const { srcPath } = model;
37
+ return {
38
+ path: path.join(srcPath, "serializeHelper.ts"),
39
+ content: readmeFileContents({})
40
+ };
41
+ }
42
+ }
@@ -0,0 +1,52 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import { NameType, normalizeName } from "./helpers/nameUtils.js";
5
+ import { RLCModel } from "./interfaces.js";
6
+ import { Project } from "ts-morph";
7
+ import * as path from "path";
8
+ import { getRelativePartFromSrcPath } from "./helpers/pathUtils.js";
9
+
10
+ const batchOutputFolder: [string, string, string][] = [];
11
+
12
+ export function buildTopLevelIndex(model: RLCModel) {
13
+ if (!model.options) {
14
+ return undefined;
15
+ }
16
+ const project = new Project();
17
+ const { srcPath } = model;
18
+ const { multiClient, batch } = model.options;
19
+ if (srcPath) {
20
+ const clientName = model.libraryName;
21
+ const moduleName = normalizeName(clientName, NameType.File);
22
+ const relativePath = "./" + getRelativePartFromSrcPath(srcPath);
23
+ batchOutputFolder.push([relativePath, clientName, moduleName]);
24
+ }
25
+ if (
26
+ multiClient &&
27
+ batch &&
28
+ batch.length > 1 &&
29
+ batchOutputFolder.length === batch.length
30
+ ) {
31
+ const indexFile = project.createSourceFile("index.ts", undefined, {
32
+ overwrite: true
33
+ });
34
+ const allModules: string[] = [];
35
+ batchOutputFolder.forEach((item) => {
36
+ indexFile.addImportDeclaration({
37
+ namespaceImport: item[1],
38
+ moduleSpecifier: `${item[0]}`
39
+ });
40
+ allModules.push(item[1]);
41
+ });
42
+ indexFile.addExportDeclaration({
43
+ namedExports: [...allModules]
44
+ });
45
+ const content = indexFile.getFullText();
46
+ const filePath = path.join(
47
+ srcPath.substring(0, srcPath.indexOf(path.sep + "src") + 4),
48
+ `index.ts`
49
+ );
50
+ return { path: filePath, content };
51
+ }
52
+ }
@@ -0,0 +1,93 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import { NameType, normalizeName } from "./nameUtils.js";
5
+
6
+ /**
7
+ * Get the response type name by baseName or operatioName & statusCode
8
+ * @param baseResponseName
9
+ */
10
+ export function getResponseTypeName(baseResponseName: string): string;
11
+ export function getResponseTypeName(
12
+ operationGroup: string,
13
+ operationName: string,
14
+ statusCode: string
15
+ ): string;
16
+ export function getResponseTypeName(
17
+ baseNameOrOperationGroup: string,
18
+ operationName?: string,
19
+ statusCode?: string
20
+ ): string {
21
+ if (operationName) {
22
+ baseNameOrOperationGroup = getResponseBaseName(
23
+ baseNameOrOperationGroup,
24
+ operationName!,
25
+ statusCode || ""
26
+ );
27
+ }
28
+ return normalizeName(
29
+ `${baseNameOrOperationGroup}Response`,
30
+ NameType.Interface
31
+ );
32
+ }
33
+
34
+ /**
35
+ * The prefix of all response types
36
+ * @param operationGroup operation group name e.g string_PutEmpty
37
+ * @param operationName operation name D e.g string_PutEmpty
38
+ * @param statusCode 2XX, 4XX, 5XX, default etc.
39
+ * @returns normolized base name e.g StringPutEmpty200
40
+ */
41
+ export function getResponseBaseName(
42
+ operationGroup: string,
43
+ operationName: string,
44
+ statusCode: string
45
+ ) {
46
+ return normalizeName(
47
+ `${operationGroup}_${operationName}_${statusCode}`,
48
+ NameType.Interface
49
+ );
50
+ }
51
+
52
+ /**
53
+ * The prefix of all parameter relevant types
54
+ * @param operationName is composed with operationGroup and operationID e.g string_PutEmpty
55
+ * @returns
56
+ */
57
+ export function getParameterBaseName(
58
+ operationGroup: string,
59
+ operationName: string
60
+ ) {
61
+ return normalizeName(
62
+ `${operationGroup}_${operationName}`,
63
+ NameType.Interface
64
+ );
65
+ }
66
+
67
+ /**
68
+ * Get the top-layer parameter name
69
+ * @param operationGroup operation group name
70
+ * @param operationName is composed with operationGroup and operationID e.g string_PutEmpty
71
+ * @returns top-layer parameter name e.g StringPutEmptParameters
72
+ */
73
+ export function getParameterTypeName(baseName: string): string;
74
+ export function getParameterTypeName(
75
+ operationGroup: string,
76
+ operationName: string
77
+ ): string;
78
+ export function getParameterTypeName(
79
+ baseNameOrOperationGroup: string,
80
+ operationName?: string
81
+ ) {
82
+ if (operationName) {
83
+ baseNameOrOperationGroup = getParameterBaseName(
84
+ baseNameOrOperationGroup,
85
+ operationName!
86
+ );
87
+ }
88
+
89
+ return normalizeName(
90
+ `${baseNameOrOperationGroup}_Parameters`,
91
+ NameType.Interface
92
+ );
93
+ }
@@ -0,0 +1,227 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ export interface ReservedName {
5
+ name: string;
6
+ reservedFor: NameType[];
7
+ }
8
+
9
+ export enum NameType {
10
+ Class,
11
+ File,
12
+ Interface,
13
+ Property,
14
+ Parameter,
15
+ Operation,
16
+ OperationGroup
17
+ }
18
+
19
+ const Newable = [NameType.Class, NameType.Interface, NameType.OperationGroup];
20
+
21
+ const ReservedModelNames: ReservedName[] = [
22
+ { name: "any", reservedFor: [NameType.Parameter] },
23
+ { name: "as", reservedFor: [NameType.Parameter] },
24
+ { name: "boolean", reservedFor: [NameType.Parameter, ...Newable] },
25
+ { name: "break", reservedFor: [NameType.Parameter] },
26
+ { name: "case", reservedFor: [NameType.Parameter] },
27
+ { name: "catch", reservedFor: [NameType.Parameter] },
28
+ { name: "class", reservedFor: [NameType.Parameter] },
29
+ { name: "const", reservedFor: [NameType.Parameter] },
30
+ { name: "constructor", reservedFor: [NameType.Parameter] },
31
+ { name: "continue", reservedFor: [NameType.Parameter] },
32
+ { name: "date", reservedFor: [NameType.Parameter, ...Newable] },
33
+ { name: "debugger", reservedFor: [NameType.Parameter] },
34
+ { name: "declare", reservedFor: [NameType.Parameter] },
35
+ { name: "default", reservedFor: [NameType.Parameter] },
36
+ { name: "delete", reservedFor: [NameType.Parameter] },
37
+ { name: "do", reservedFor: [NameType.Parameter] },
38
+ { name: "else", reservedFor: [NameType.Parameter] },
39
+ { name: "enum", reservedFor: [NameType.Parameter] },
40
+ { name: "error", reservedFor: [NameType.Parameter, ...Newable] },
41
+ { name: "export", reservedFor: [NameType.Parameter] },
42
+ { name: "extends", reservedFor: [NameType.Parameter] },
43
+ { name: "false", reservedFor: [NameType.Parameter] },
44
+ { name: "finally", reservedFor: [NameType.Parameter] },
45
+ { name: "for", reservedFor: [NameType.Parameter] },
46
+ { name: "from", reservedFor: [NameType.Parameter] },
47
+ { name: "function", reservedFor: [NameType.Parameter, ...Newable] },
48
+ { name: "get", reservedFor: [NameType.Parameter] },
49
+ { name: "if", reservedFor: [NameType.Parameter] },
50
+ { name: "implements", reservedFor: [NameType.Parameter] },
51
+ { name: "import", reservedFor: [NameType.Parameter] },
52
+ { name: "in", reservedFor: [NameType.Parameter] },
53
+ { name: "instanceof", reservedFor: [NameType.Parameter] },
54
+ { name: "interface", reservedFor: [NameType.Parameter] },
55
+ { name: "let", reservedFor: [NameType.Parameter] },
56
+ { name: "module", reservedFor: [NameType.Parameter] },
57
+ { name: "new", reservedFor: [NameType.Parameter] },
58
+ { name: "null", reservedFor: [NameType.Parameter] },
59
+ { name: "number", reservedFor: [NameType.Parameter, ...Newable] },
60
+ { name: "of", reservedFor: [NameType.Parameter] },
61
+ { name: "package", reservedFor: [NameType.Parameter] },
62
+ { name: "private", reservedFor: [NameType.Parameter] },
63
+ { name: "protected", reservedFor: [NameType.Parameter] },
64
+ { name: "public", reservedFor: [NameType.Parameter] },
65
+ { name: "requestoptions", reservedFor: [NameType.Parameter] },
66
+ { name: "require", reservedFor: [NameType.Parameter] },
67
+ { name: "return", reservedFor: [NameType.Parameter] },
68
+ { name: "set", reservedFor: [NameType.Parameter, ...Newable] },
69
+ { name: "static", reservedFor: [NameType.Parameter] },
70
+ { name: "string", reservedFor: [NameType.Parameter, ...Newable] },
71
+ { name: "super", reservedFor: [NameType.Parameter] },
72
+ { name: "switch", reservedFor: [NameType.Parameter] },
73
+ { name: "symbol", reservedFor: [NameType.Parameter, ...Newable] },
74
+ { name: "this", reservedFor: [NameType.Parameter] },
75
+ { name: "throw", reservedFor: [NameType.Parameter] },
76
+ { name: "true", reservedFor: [NameType.Parameter] },
77
+ { name: "try", reservedFor: [NameType.Parameter] },
78
+ { name: "type", reservedFor: [NameType.Parameter] },
79
+ { name: "typeof", reservedFor: [NameType.Parameter] },
80
+ { name: "var", reservedFor: [NameType.Parameter] },
81
+ { name: "void", reservedFor: [NameType.Parameter] },
82
+ { name: "while", reservedFor: [NameType.Parameter] },
83
+ { name: "with", reservedFor: [NameType.Parameter] },
84
+ { name: "yield", reservedFor: [NameType.Parameter] },
85
+ { name: "arguments", reservedFor: [NameType.Parameter] }
86
+ ];
87
+
88
+ export enum CasingConvention {
89
+ Pascal,
90
+ Camel
91
+ }
92
+
93
+ export function guardReservedNames(
94
+ name: string,
95
+ nameType: NameType,
96
+ customReservedNames: ReservedName[] = []
97
+ ): string {
98
+ const suffix = getSuffix(nameType);
99
+ return [...ReservedModelNames, ...customReservedNames]
100
+ .filter((r) => r.reservedFor.includes(nameType))
101
+ .find((r) => r.name === name.toLowerCase())
102
+ ? `${name}${suffix}`
103
+ : name;
104
+ }
105
+
106
+ function getSuffix(nameType?: NameType) {
107
+ switch (nameType) {
108
+ case NameType.File:
109
+ case NameType.Operation:
110
+ case NameType.Property:
111
+ return "";
112
+ case NameType.OperationGroup:
113
+ return "Operations";
114
+ case NameType.Parameter:
115
+ return "Param";
116
+ case NameType.Class:
117
+ case NameType.Interface:
118
+ default:
119
+ return "Model";
120
+ }
121
+ }
122
+
123
+ export function normalizeName(
124
+ name: string,
125
+ nameType: NameType,
126
+ shouldGuard?: boolean,
127
+ customReservedNames: ReservedName[] = [],
128
+ casingOverride?: CasingConvention
129
+ ): string {
130
+ if (name.startsWith("$DO_NOT_NORMALIZE$")) {
131
+ return name.replace("$DO_NOT_NORMALIZE$", "");
132
+ }
133
+ const casingConvention = casingOverride ?? getCasingConvention(nameType);
134
+ const sanitizedName = sanitizeName(name);
135
+ const parts = getNameParts(sanitizedName);
136
+ const [firstPart, ...otherParts] = parts;
137
+ const normalizedFirstPart = toCasing(firstPart, casingConvention);
138
+ const normalizedParts = (otherParts || [])
139
+ .map((part) =>
140
+ part === "null" ? part : toCasing(part, CasingConvention.Pascal)
141
+ )
142
+ .join("");
143
+
144
+ const normalized = checkBeginning(`${normalizedFirstPart}${normalizedParts}`);
145
+ return shouldGuard
146
+ ? guardReservedNames(normalized, nameType, customReservedNames)
147
+ : normalized;
148
+ }
149
+
150
+ function checkBeginning(name: string): string {
151
+ if (name.startsWith("@")) {
152
+ return name.substring(1);
153
+ }
154
+ return name;
155
+ }
156
+
157
+ function sanitizeName(name: string): string {
158
+ // Remove \, " and ' from name string
159
+ return name.replace(/["'\\]+/g, "");
160
+ }
161
+
162
+ export function getModelsName(title: string): string {
163
+ const spaceRemovedTitle = title.replace(/ /g, "");
164
+ return `${spaceRemovedTitle.replace("Client", "")}Models`;
165
+ }
166
+
167
+ export function getMappersName(title: string): string {
168
+ const spaceRemovedTitle = title.replace(/ /g, "");
169
+ return `${spaceRemovedTitle.replace("Client", "")}Mappers`;
170
+ }
171
+
172
+ function getCasingConvention(nameType: NameType) {
173
+ switch (nameType) {
174
+ case NameType.Class:
175
+ case NameType.Interface:
176
+ case NameType.OperationGroup:
177
+ return CasingConvention.Pascal;
178
+ case NameType.File:
179
+ case NameType.Property:
180
+ case NameType.Operation:
181
+ case NameType.Parameter:
182
+ return CasingConvention.Camel;
183
+ }
184
+ }
185
+
186
+ /**
187
+ * TODO: Improve this function to handle cases such as TEST -> test. Current basic implementation
188
+ * results in TEST -> test or Test (depending on the CasingConvention). We should switch to relay
189
+ * on Modeler four namer for this once it is stable
190
+ */
191
+ function toCasing(str: string, casing: CasingConvention): string {
192
+ let value = str;
193
+ if (value === value.toUpperCase()) {
194
+ value = str.toLowerCase();
195
+ }
196
+
197
+ const firstChar =
198
+ casing === CasingConvention.Pascal
199
+ ? value.charAt(0).toUpperCase()
200
+ : value.charAt(0).toLocaleLowerCase();
201
+ return `${firstChar}${value.substring(1)}`;
202
+ }
203
+
204
+ function getNameParts(name: string) {
205
+ const parts = name.split(/[-._ ]+/);
206
+
207
+ return parts.length > 0 ? parts : [name];
208
+ }
209
+
210
+ export function pascalCase(str: string) {
211
+ return str.charAt(0).toUpperCase() + str.slice(1);
212
+ }
213
+
214
+ export function camelCase(
215
+ str: string,
216
+ options: { uppercaseThreshold?: number } = {}
217
+ ) {
218
+ const { uppercaseThreshold = 4 } = options;
219
+ const thresholdRegex = new RegExp(
220
+ `^(?<![A-Z])[A-Z]{1,${uppercaseThreshold}}(?![A-Z])`
221
+ );
222
+ if (!thresholdRegex.test(str)) {
223
+ return str;
224
+ }
225
+
226
+ return str.charAt(0).toLocaleLowerCase() + str.slice(1);
227
+ }
@@ -0,0 +1,119 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import {
5
+ MethodSignatureStructure,
6
+ OptionalKind,
7
+ ParameterDeclarationStructure
8
+ } from "ts-morph";
9
+ import {
10
+ Methods,
11
+ ObjectSchema,
12
+ PathParameter,
13
+ RLCModel,
14
+ SchemaContext
15
+ } from "../interfaces.js";
16
+ import { NameType, normalizeName, pascalCase } from "./nameUtils.js";
17
+ import { isObjectSchema } from "./schemaHelpers.js";
18
+
19
+ export function buildMethodDefinitions(
20
+ methods: Methods,
21
+ pathParams: PathParameter[] = []
22
+ ): OptionalKind<MethodSignatureStructure>[] {
23
+ const methodDefinitions: OptionalKind<MethodSignatureStructure>[] = [];
24
+ for (const key of Object.keys(methods)) {
25
+ const verbMethods = methods[key];
26
+
27
+ for (const method of verbMethods) {
28
+ const description = method.description;
29
+ const areAllOptional = method.hasOptionalOptions;
30
+
31
+ methodDefinitions.push({
32
+ name: key,
33
+ ...(description && { docs: [{ description }] }),
34
+ parameters: [
35
+ ...getPathParamDefinitions(pathParams),
36
+ {
37
+ name: "options",
38
+ hasQuestionToken: areAllOptional,
39
+ type: pascalCase(method.optionsName)
40
+ }
41
+ ],
42
+ returnType: `StreamableMethod<${method.returnType}>`
43
+ });
44
+ }
45
+ }
46
+
47
+ return methodDefinitions;
48
+ }
49
+
50
+ export function getPathParamDefinitions(
51
+ pathParams: PathParameter[]
52
+ ): OptionalKind<ParameterDeclarationStructure>[] {
53
+ return pathParams.map(({ name, type, description }) => {
54
+ return {
55
+ name: normalizeName(name, NameType.Parameter),
56
+ type,
57
+ description
58
+ };
59
+ });
60
+ }
61
+
62
+ export function hasPagingOperations(model: RLCModel) {
63
+ return Boolean(model.annotations?.hasPaging);
64
+ }
65
+
66
+ export function hasPollingOperations(model: RLCModel) {
67
+ return Boolean(model.annotations?.hasLongRunning);
68
+ }
69
+
70
+ export function hasMultiCollection(model: RLCModel) {
71
+ return Boolean(model.annotations?.hasMultiCollection);
72
+ }
73
+
74
+ export function hasPipeCollection(model: RLCModel) {
75
+ return Boolean(model.annotations?.hasPipeCollection);
76
+ }
77
+
78
+ export function hasSsvCollection(model: RLCModel) {
79
+ return Boolean(model.annotations?.hasSsvCollection);
80
+ }
81
+
82
+ export function hasTsvCollection(model: RLCModel) {
83
+ return Boolean(model.annotations?.hasTsvCollection);
84
+ }
85
+
86
+ export function hasUnexpectedHelper(model: RLCModel) {
87
+ const pathDictionary = model.paths;
88
+ for (const details of Object.values(pathDictionary)) {
89
+ for (const methodDetails of Object.values(details.methods)) {
90
+ const successTypes = methodDetails[0].responseTypes.success;
91
+ const errorTypes = methodDetails[0].responseTypes.error;
92
+
93
+ if (successTypes.length > 0 && errorTypes.length > 0 && !!errorTypes[0]) {
94
+ return true;
95
+ }
96
+ }
97
+ }
98
+ return false;
99
+ }
100
+
101
+ export function hasInputModels(model: RLCModel) {
102
+ return hasSchemaContextObject(model, [SchemaContext.Input]);
103
+ }
104
+ export function hasOutputModels(model: RLCModel) {
105
+ return hasSchemaContextObject(model, [
106
+ SchemaContext.Output,
107
+ SchemaContext.Exception
108
+ ]);
109
+ }
110
+
111
+ function hasSchemaContextObject(model: RLCModel, schemaUsage: SchemaContext[]) {
112
+ const objectSchemas: ObjectSchema[] = (model.schemas ?? []).filter(
113
+ (o) =>
114
+ isObjectSchema(o) &&
115
+ (o as ObjectSchema).usage?.some((u) => schemaUsage.includes(u))
116
+ );
117
+
118
+ return objectSchemas.length > 0;
119
+ }
@@ -0,0 +1,9 @@
1
+ import * as path from "path";
2
+
3
+ export function getRelativePartFromSrcPath(srcPath: string) {
4
+ const sep = srcPath.includes(path.sep + "src") ? path.sep : "/";
5
+ const relativePart = srcPath.substring(srcPath.indexOf(sep + "src") + 4);
6
+ return relativePart.startsWith(sep)
7
+ ? relativePart.substring(1)
8
+ : relativePart;
9
+ }
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import { Schema } from "../interfaces.js";
5
+
6
+ export function isDictionarySchema(schema: Schema) {
7
+ if (schema.type === "dictionary") {
8
+ return true;
9
+ }
10
+ return false;
11
+ }
12
+
13
+ export function isObjectSchema(schema: Schema) {
14
+ if (schema.type === "object") {
15
+ return true;
16
+ }
17
+ return false;
18
+ }
19
+
20
+ export function isConstantSchema(schema: Schema) {
21
+ if (schema.type === "constant") {
22
+ return true;
23
+ }
24
+ return false;
25
+ }