@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,202 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import { Project, SourceFile } from "ts-morph";
5
+ import { NameType, normalizeName } from "./helpers/nameUtils.js";
6
+ import {
7
+ hasInputModels,
8
+ hasMultiCollection,
9
+ hasOutputModels,
10
+ hasPagingOperations,
11
+ hasPipeCollection,
12
+ hasPollingOperations,
13
+ hasSsvCollection,
14
+ hasTsvCollection,
15
+ hasUnexpectedHelper
16
+ } from "./helpers/operationHelpers.js";
17
+ import { RLCModel } from "./interfaces.js";
18
+ import * as path from "path";
19
+
20
+ export function buildIndexFile(model: RLCModel) {
21
+ const multiClient = Boolean(model.options?.multiClient),
22
+ batch = model.options?.batch;
23
+ const project = new Project();
24
+ const { srcPath } = model;
25
+ const filePath = path.join(srcPath, `index.ts`);
26
+ const indexFile = project.createSourceFile(filePath, undefined, {
27
+ overwrite: true
28
+ });
29
+
30
+ if (!multiClient || !batch || batch?.length === 1) {
31
+ // if we are generate single client package for RLC
32
+ generateRLCIndex(indexFile, model);
33
+ } else {
34
+ generateRLCIndexForMultiClient(indexFile, model);
35
+ }
36
+ return {
37
+ path: filePath,
38
+ content: indexFile.getFullText()
39
+ };
40
+ }
41
+
42
+ // to generate a index.ts for each single module inside the multi client RLC package
43
+ function generateRLCIndexForMultiClient(file: SourceFile, model: RLCModel) {
44
+ const clientName = model.libraryName;
45
+ const createClientFuncName = `createClient`;
46
+ const moduleName = normalizeName(clientName, NameType.File);
47
+
48
+ file.addImportDeclaration({
49
+ namespaceImport: "Parameters",
50
+ moduleSpecifier: "./parameters"
51
+ });
52
+
53
+ file.addImportDeclaration({
54
+ namespaceImport: "Responses",
55
+ moduleSpecifier: "./responses"
56
+ });
57
+
58
+ file.addImportDeclaration({
59
+ namespaceImport: "Client",
60
+ moduleSpecifier: "./clientDefinitions"
61
+ });
62
+
63
+ const exports = ["Parameters", "Responses", "Client"];
64
+ if (hasInputModels(model)) {
65
+ file.addImportDeclaration({
66
+ namespaceImport: "Models",
67
+ moduleSpecifier: "./models"
68
+ });
69
+ exports.push("Models");
70
+ }
71
+
72
+ if (hasOutputModels(model)) {
73
+ file.addImportDeclaration({
74
+ namespaceImport: "OutputModels",
75
+ moduleSpecifier: "./outputModels"
76
+ });
77
+ exports.push("OutputModels");
78
+ }
79
+
80
+ if (hasPagingOperations(model)) {
81
+ file.addImportDeclaration({
82
+ namespaceImport: "PaginateHelper",
83
+ moduleSpecifier: "./paginateHelper"
84
+ });
85
+ exports.push("PaginateHelper");
86
+ }
87
+
88
+ if (hasPollingOperations(model)) {
89
+ file.addImportDeclaration({
90
+ namespaceImport: "PollingHelper",
91
+ moduleSpecifier: "./pollingHelper"
92
+ });
93
+ exports.push("PollingHelper");
94
+ }
95
+
96
+ if (
97
+ hasMultiCollection(model) ||
98
+ hasSsvCollection(model) ||
99
+ hasPipeCollection(model) ||
100
+ hasTsvCollection(model)
101
+ ) {
102
+ file.addImportDeclaration({
103
+ namespaceImport: "SerializeHelper",
104
+ moduleSpecifier: "./serializeHelper"
105
+ });
106
+ exports.push("SerializeHelper");
107
+ }
108
+
109
+ file.addExportDeclarations([
110
+ {
111
+ moduleSpecifier: `./${moduleName}`,
112
+ namedExports: [`${createClientFuncName}`]
113
+ },
114
+ {
115
+ namedExports: [...exports]
116
+ }
117
+ ]);
118
+ }
119
+
120
+ function generateRLCIndex(file: SourceFile, model: RLCModel) {
121
+ const clientName = model.libraryName;
122
+ const createClientFuncName = `${clientName}`;
123
+ const moduleName = normalizeName(clientName, NameType.File);
124
+
125
+ file.addImportDeclaration({
126
+ moduleSpecifier: `./${moduleName}`,
127
+ defaultImport: createClientFuncName
128
+ });
129
+
130
+ file.addExportDeclarations([
131
+ {
132
+ moduleSpecifier: `./${moduleName}`
133
+ },
134
+ {
135
+ moduleSpecifier: "./parameters"
136
+ },
137
+ {
138
+ moduleSpecifier: "./responses"
139
+ },
140
+ {
141
+ moduleSpecifier: "./clientDefinitions"
142
+ }
143
+ ]);
144
+
145
+ if (hasUnexpectedHelper(model)) {
146
+ file.addExportDeclarations([
147
+ {
148
+ moduleSpecifier: "./isUnexpected"
149
+ }
150
+ ]);
151
+ }
152
+
153
+ if (hasInputModels(model)) {
154
+ file.addExportDeclarations([
155
+ {
156
+ moduleSpecifier: "./models"
157
+ }
158
+ ]);
159
+ }
160
+
161
+ if (hasOutputModels(model)) {
162
+ file.addExportDeclarations([
163
+ {
164
+ moduleSpecifier: "./outputModels"
165
+ }
166
+ ]);
167
+ }
168
+
169
+ if (hasPagingOperations(model)) {
170
+ file.addExportDeclarations([
171
+ {
172
+ moduleSpecifier: "./paginateHelper"
173
+ }
174
+ ]);
175
+ }
176
+
177
+ if (hasPollingOperations(model)) {
178
+ file.addExportDeclarations([
179
+ {
180
+ moduleSpecifier: "./pollingHelper"
181
+ }
182
+ ]);
183
+ }
184
+
185
+ if (
186
+ hasMultiCollection(model) ||
187
+ hasSsvCollection(model) ||
188
+ hasPipeCollection(model) ||
189
+ hasTsvCollection(model)
190
+ ) {
191
+ file.addExportDeclarations([
192
+ {
193
+ moduleSpecifier: "./serializeHelper"
194
+ }
195
+ ]);
196
+ }
197
+
198
+ file.addExportAssignment({
199
+ expression: createClientFuncName,
200
+ isExportEquals: false
201
+ });
202
+ }
@@ -0,0 +1,240 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import { Paths, RLCModel } from "./interfaces.js";
5
+ import * as path from "path";
6
+ import {
7
+ FunctionDeclarationOverloadStructure,
8
+ OptionalKind,
9
+ Project,
10
+ VariableDeclarationKind
11
+ } from "ts-morph";
12
+ import { hasUnexpectedHelper } from "./helpers/operationHelpers.js";
13
+ export function buildIsUnexpectedHelper(model: RLCModel) {
14
+ if (!hasUnexpectedHelper(model)) {
15
+ return;
16
+ }
17
+ const project = new Project();
18
+ const srcPath = model.srcPath;
19
+ const filePath = path.join(srcPath, `isUnexpected.ts`);
20
+ const isErrorHelper = project.createSourceFile(filePath, undefined, {
21
+ overwrite: true
22
+ });
23
+
24
+ let map: Record<string, string[]> = {};
25
+ const allResponseTypes: Set<string> = new Set();
26
+ const allErrorTypes: Set<string> = new Set();
27
+ const overloads: OptionalKind<FunctionDeclarationOverloadStructure>[] = [];
28
+ const pathDictionary = model.paths;
29
+
30
+ for (const [path, details] of Object.entries(pathDictionary)) {
31
+ for (const [methodName, methodDetails] of Object.entries(details.methods)) {
32
+ const originalMethod = methodName.toUpperCase();
33
+ const operation = `${originalMethod} ${path}`;
34
+ const success = methodDetails[0].successStatus;
35
+ map = { ...map, ...{ [operation]: success } };
36
+
37
+ // LROs may call the same path but with GET
38
+ // to get the operation status.
39
+ if (
40
+ methodDetails[0].annotations?.isLongRunning &&
41
+ originalMethod !== "GET"
42
+ ) {
43
+ const operation = `GET ${path}`;
44
+ const success =
45
+ (pathDictionary[path].methods["get"] &&
46
+ pathDictionary[path].methods["get"][0]?.successStatus) ??
47
+ methodDetails[0].successStatus;
48
+ map = { ...map, ...{ [operation]: success } };
49
+ }
50
+
51
+ const successTypes = methodDetails[0].responseTypes.success;
52
+ const errorTypes = methodDetails[0].responseTypes.error;
53
+
54
+ if (!successTypes.length || !errorTypes.length || !errorTypes[0]) {
55
+ continue;
56
+ }
57
+
58
+ successTypes.forEach((t) => allResponseTypes.add(t));
59
+ errorTypes.forEach((t) => {
60
+ allResponseTypes.add(t);
61
+ allErrorTypes.add(t);
62
+ });
63
+
64
+ overloads.push({
65
+ isExported: true,
66
+ parameters: [
67
+ {
68
+ name: "response",
69
+ type: [...successTypes, ...errorTypes].join(" | ")
70
+ }
71
+ ],
72
+ returnType: `response is ${errorTypes[0]}`
73
+ });
74
+ }
75
+ }
76
+ isErrorHelper.addImportDeclaration({
77
+ namedImports: [...allResponseTypes],
78
+ moduleSpecifier: "./responses"
79
+ });
80
+
81
+ isErrorHelper.addVariableStatement({
82
+ declarations: [
83
+ {
84
+ name: "responseMap",
85
+ initializer: JSON.stringify(map),
86
+ type: "Record<string, string[]>"
87
+ }
88
+ ],
89
+ declarationKind: VariableDeclarationKind.Const
90
+ });
91
+
92
+ if (allErrorTypes.size) {
93
+ const hasTemplate = hasParametrizedPath(pathDictionary);
94
+ isErrorHelper.addFunction({
95
+ overloads,
96
+ isExported: true,
97
+ name: "isUnexpected",
98
+ parameters: [
99
+ {
100
+ name: "response",
101
+ type: [...allResponseTypes].join(" | ")
102
+ }
103
+ ],
104
+ returnType: `response is ${[...allErrorTypes].join(" | ")}`,
105
+ statements: [
106
+ `
107
+ const lroOriginal = response.headers["x-ms-original-url"];
108
+ const url = new URL(lroOriginal ?? response.request.url);
109
+ const method = response.request.method;
110
+ ${
111
+ hasTemplate ? "let" : "const"
112
+ } pathDetails = responseMap[\`\${method} \${url.pathname}\`];
113
+ if (!pathDetails) {`,
114
+ hasTemplate
115
+ ? "pathDetails = getParametrizedPathSuccess(method, url.pathname);"
116
+ : `return true;`,
117
+ ` }
118
+ return !pathDetails.includes(response.status);
119
+ `
120
+ ]
121
+ });
122
+ if (hasTemplate) {
123
+ isErrorHelper.addFunction({
124
+ isExported: false,
125
+ name: "getParametrizedPathSuccess",
126
+ parameters: [
127
+ {
128
+ name: "method",
129
+ type: "string"
130
+ },
131
+ {
132
+ name: "path",
133
+ type: "string"
134
+ }
135
+ ],
136
+ returnType: `string[]`,
137
+ statements: [
138
+ `
139
+ const pathParts = path.split("/");
140
+
141
+ // Traverse list to match the longest candidate
142
+ // matchedLen: the length of candidate path
143
+ // matchedValue: the matched status code array
144
+ let matchedLen = -1,
145
+ matchedValue: string[] = [];
146
+
147
+ // Iterate the responseMap to find a match
148
+ for (const [key, value] of Object.entries(responseMap)) {
149
+ // Extracting the path from the map key which is in format
150
+ // GET /path/foo
151
+ if (!key.startsWith(method)) {
152
+ continue;
153
+ }
154
+ const candidatePath = getPathFromMapKey(key);
155
+ // Get each part of the url path
156
+ const candidateParts = candidatePath.split("/");
157
+
158
+ // track if we have found a match to return the values found.
159
+ let found = true;
160
+ for (
161
+ let i = candidateParts.length - 1, j = pathParts.length - 1;
162
+ i >= 1 && j >= 1;
163
+ i--, j--
164
+ ) {
165
+ if (
166
+ candidateParts[i]?.startsWith("{") &&
167
+ candidateParts[i]?.indexOf("}") !== -1
168
+ ) {
169
+ const start = candidateParts[i]!.indexOf("}") + 1,
170
+ end = candidateParts[i]?.length;
171
+ // If the current part of the candidate is a "template" part
172
+ // Try to use the suffix of pattern to match the path
173
+ // {guid} ==> $
174
+ // {guid}:export ==> :export$
175
+ const isMatched = new RegExp(
176
+ \`\${candidateParts[i]?.slice(start, end)}\`
177
+ ).test(pathParts[j] || '');
178
+
179
+ if (!isMatched) {
180
+ found = false;
181
+ break;
182
+ }
183
+ continue;
184
+ }
185
+
186
+ // If the candidate part is not a template and
187
+ // the parts don't match mark the candidate as not found
188
+ // to move on with the next candidate path.
189
+ if (candidateParts[i] !== pathParts[j]) {
190
+ found = false;
191
+ break;
192
+ }
193
+ }
194
+
195
+ // We finished evaluating the current candidate parts
196
+ // Update the matched value if and only if we found the longer pattern
197
+ if (found && candidatePath.length > matchedLen) {
198
+ matchedLen = candidatePath.length;
199
+ matchedValue = value;
200
+ }
201
+ }
202
+
203
+ return matchedValue;
204
+ `
205
+ ]
206
+ });
207
+
208
+ isErrorHelper.addFunction({
209
+ isExported: false,
210
+ name: "getPathFromMapKey",
211
+ parameters: [
212
+ {
213
+ name: "mapKey",
214
+ type: "string"
215
+ }
216
+ ],
217
+ returnType: `string`,
218
+ statements: [
219
+ `const pathStart = mapKey.indexOf("/");
220
+ return mapKey.slice(pathStart);`
221
+ ]
222
+ });
223
+ }
224
+ }
225
+
226
+ return {
227
+ path: filePath,
228
+ content: isErrorHelper.getFullText()
229
+ };
230
+ }
231
+
232
+ function hasParametrizedPath(pathDictionary: Paths): boolean {
233
+ for (const [path] of Object.entries(pathDictionary)) {
234
+ if (path.includes("/{") && path.includes("}")) {
235
+ return true;
236
+ }
237
+ }
238
+
239
+ return false;
240
+ }
@@ -0,0 +1,75 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import {
5
+ CasingConvention,
6
+ NameType,
7
+ normalizeName,
8
+ ReservedName
9
+ } from "./helpers/nameUtils.js";
10
+ import { Paths, PathParameter, PathMetadata } from "./interfaces.js";
11
+
12
+ export const REST_CLIENT_RESERVED: ReservedName[] = [
13
+ { name: "path", reservedFor: [NameType.Property, NameType.OperationGroup] },
14
+ {
15
+ name: "pathUnchecked",
16
+ reservedFor: [NameType.Property, NameType.OperationGroup]
17
+ },
18
+ {
19
+ name: "pipeline",
20
+ reservedFor: [NameType.Property, NameType.OperationGroup]
21
+ }
22
+ ];
23
+
24
+ export function buildMethodShortcutImplementation(paths: Paths) {
25
+ const keys: Record<string, string[]> = {};
26
+ for (const path of Object.keys(paths)) {
27
+ const groupName = normalizeName(
28
+ paths[path].operationGroupName,
29
+ NameType.OperationGroup,
30
+ true,
31
+ REST_CLIENT_RESERVED,
32
+ CasingConvention.Camel
33
+ );
34
+
35
+ if (keys[groupName]) {
36
+ keys[groupName].push(...buildOperationDeclarations(path, paths[path]));
37
+ } else {
38
+ keys[groupName] = buildOperationDeclarations(path, paths[path]);
39
+ }
40
+ }
41
+ return keys;
42
+ }
43
+
44
+ function buildOperationDeclarations(path: string, pathMetadata: PathMetadata) {
45
+ let ops: string[] = [];
46
+ for (const method of Object.keys(pathMetadata.methods)) {
47
+ for (const op of pathMetadata.methods[method]) {
48
+ const pathParams = pathMetadata?.pathParameters;
49
+ const name = normalizeName(op.operationName, NameType.Property);
50
+ const methodDefinitions = generateOperationDeclaration(
51
+ path,
52
+ name,
53
+ method,
54
+ pathParams
55
+ );
56
+ ops = [...ops, methodDefinitions];
57
+ }
58
+ }
59
+
60
+ return ops;
61
+ }
62
+
63
+ function generateOperationDeclaration(
64
+ path: string,
65
+ operationName: string,
66
+ method: string,
67
+ pathParams: PathParameter[] = []
68
+ ): string {
69
+ const pathParamNames = `${
70
+ pathParams.length > 0 ? `${pathParams.map((p) => p.name)},` : ""
71
+ }`;
72
+ return `"${operationName}": (${pathParamNames} options) => {
73
+ return client.path("${path}", ${pathParamNames}).${method}(options);
74
+ }`;
75
+ }