@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,449 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ import {
5
+ InterfaceDeclarationStructure,
6
+ PropertySignatureStructure,
7
+ StructureKind,
8
+ TypeAliasDeclarationStructure
9
+ } from "ts-morph";
10
+ import { NameType, normalizeName } from "./helpers/nameUtils.js";
11
+ import { isDictionarySchema, isObjectSchema } from "./helpers/schemaHelpers.js";
12
+ import {
13
+ ObjectSchema,
14
+ Parameter,
15
+ Property,
16
+ RLCModel,
17
+ SchemaContext
18
+ } from "./interfaces.js";
19
+
20
+ /**
21
+ * Generates interfaces for ObjectSchemas
22
+ */
23
+ export function buildObjectInterfaces(
24
+ model: RLCModel,
25
+ importedModels: Set<string>,
26
+ schemaUsage: SchemaContext[]
27
+ ): InterfaceDeclarationStructure[] {
28
+ const objectSchemas: ObjectSchema[] = (model.schemas ?? []).filter(
29
+ (o) =>
30
+ isObjectSchema(o) &&
31
+ (o as ObjectSchema).usage?.some((u) => schemaUsage.includes(u))
32
+ );
33
+ const objectInterfaces: InterfaceDeclarationStructure[] = [];
34
+
35
+ for (const objectSchema of objectSchemas) {
36
+ if (objectSchema.alias || objectSchema.outputAlias) {
37
+ continue;
38
+ }
39
+ const baseName = getObjectBaseName(objectSchema, schemaUsage);
40
+ const interfaceDeclaration = getObjectInterfaceDeclaration(
41
+ baseName,
42
+ objectSchema,
43
+ schemaUsage,
44
+ importedModels
45
+ );
46
+
47
+ objectInterfaces.push(interfaceDeclaration);
48
+ }
49
+ return objectInterfaces;
50
+ }
51
+
52
+ export function buildObjectAliases(
53
+ model: RLCModel,
54
+ importedModels: Set<string>,
55
+ schemaUsage: SchemaContext[]
56
+ ) {
57
+ const objectSchemas: ObjectSchema[] = (model.schemas ?? []).filter(
58
+ (o) =>
59
+ isObjectSchema(o) &&
60
+ (o as ObjectSchema).usage?.some((u) => schemaUsage.includes(u))
61
+ );
62
+ const objectAliases: TypeAliasDeclarationStructure[] = [];
63
+
64
+ for (const objectSchema of objectSchemas) {
65
+ if (objectSchema.alias || objectSchema.outputAlias) {
66
+ const description = objectSchema.description;
67
+ objectAliases.push({
68
+ kind: StructureKind.TypeAlias,
69
+ ...(description && { docs: [{ description }] }),
70
+ name: schemaUsage.includes(SchemaContext.Input)
71
+ ? `${objectSchema.typeName}`
72
+ : `${objectSchema.outputTypeName}`,
73
+ type: schemaUsage.includes(SchemaContext.Input)
74
+ ? `${objectSchema.alias}`
75
+ : `${objectSchema.outputAlias}`,
76
+ isExported: true
77
+ });
78
+ if (objectSchema.alias?.startsWith("Paged<")) {
79
+ importedModels.add("Paged");
80
+ }
81
+ }
82
+ }
83
+ return objectAliases;
84
+ }
85
+
86
+ export function buildPolymorphicAliases(
87
+ model: RLCModel,
88
+ schemaUsage: SchemaContext[]
89
+ ) {
90
+ // We'll add aliases for polymorphic objects
91
+ const objectAliases: TypeAliasDeclarationStructure[] = [];
92
+ const objectSchemas: ObjectSchema[] = (model.schemas ?? []).filter(
93
+ (o) =>
94
+ isObjectSchema(o) &&
95
+ (o as ObjectSchema).usage?.some((u) => schemaUsage.includes(u))
96
+ );
97
+ for (const objectSchema of objectSchemas) {
98
+ const baseName = getObjectBaseName(objectSchema, schemaUsage);
99
+ const typeAlias = getPolymorphicTypeAlias(
100
+ baseName,
101
+ objectSchema,
102
+ schemaUsage
103
+ );
104
+ if (typeAlias) {
105
+ objectAliases.push(typeAlias);
106
+ }
107
+ }
108
+
109
+ return objectAliases;
110
+ }
111
+
112
+ /**
113
+ * Gets a base name for an object schema this is tipically used with suffixes when building interface or type names
114
+ */
115
+ function getObjectBaseName(
116
+ objectSchema: ObjectSchema,
117
+ schemaUsage: SchemaContext[]
118
+ ) {
119
+ const nameSuffix = schemaUsage.includes(SchemaContext.Output) ? "Output" : "";
120
+ const name = normalizeName(
121
+ objectSchema.name,
122
+ NameType.Interface,
123
+ true /** guard name */
124
+ );
125
+
126
+ return `${name}${nameSuffix}`;
127
+ }
128
+
129
+ /**
130
+ * If the current object is a Polymorphic parent, we need to create
131
+ * a type alias with the union of its children to enable polymorphism
132
+ */
133
+ function getPolymorphicTypeAlias(
134
+ baseName: string,
135
+ objectSchema: ObjectSchema,
136
+ schemaUsage: SchemaContext[]
137
+ ): TypeAliasDeclarationStructure | undefined {
138
+ if (!isPolymorphicParent(objectSchema)) {
139
+ return undefined;
140
+ }
141
+
142
+ const unionTypes: string[] = [];
143
+
144
+ // If the object itself has a discriminatorValue add its base to the union
145
+ if (objectSchema.discriminatorValue) {
146
+ unionTypes.push(`${baseName}Parent`);
147
+ }
148
+
149
+ for (const child of objectSchema.children?.all ?? []) {
150
+ const nameSuffix = schemaUsage.includes(SchemaContext.Output)
151
+ ? "Output"
152
+ : "";
153
+ const name = normalizeName(
154
+ child.name,
155
+ NameType.Interface,
156
+ true /** shouldGuard */
157
+ );
158
+
159
+ unionTypes.push(`${name}${nameSuffix}`);
160
+ }
161
+
162
+ const description = objectSchema.description;
163
+
164
+ return {
165
+ kind: StructureKind.TypeAlias,
166
+ ...(description && { docs: [{ description }] }),
167
+ name: `${baseName}`,
168
+ type: unionTypes.join(" | "),
169
+ isExported: true
170
+ };
171
+ }
172
+
173
+ /**
174
+ * Builds the interface for the current object schema. If it is a polymorphic
175
+ * root node it will suffix it with Base.
176
+ */
177
+ function getObjectInterfaceDeclaration(
178
+ baseName: string,
179
+ objectSchema: ObjectSchema,
180
+ schemaUsage: SchemaContext[],
181
+ importedModels: Set<string>
182
+ ): InterfaceDeclarationStructure {
183
+ let interfaceName = `${baseName}`;
184
+ if (isPolymorphicParent(objectSchema)) {
185
+ interfaceName = `${baseName}Parent`;
186
+ }
187
+
188
+ const properties = objectSchema.properties ?? {};
189
+
190
+ let propertySignatures = getPropertySignatures(
191
+ properties,
192
+ schemaUsage,
193
+ importedModels
194
+ );
195
+
196
+ // Add the polymorphic property if exists
197
+ propertySignatures = addDiscriminatorProperty(
198
+ objectSchema,
199
+ propertySignatures
200
+ );
201
+
202
+ // Calculate the parents of the current object
203
+ const extendFrom = getImmediateParentsNames(objectSchema, schemaUsage);
204
+
205
+ const description = objectSchema.description;
206
+ return {
207
+ kind: StructureKind.Interface,
208
+ ...(description && { docs: [{ description }] }),
209
+ name: interfaceName,
210
+ isExported: true,
211
+ properties: propertySignatures,
212
+ ...(extendFrom && { extends: extendFrom })
213
+ };
214
+ }
215
+
216
+ function isPolymorphicParent(objectSchema: ObjectSchema) {
217
+ return objectSchema.isPolyParent ? true : false;
218
+ }
219
+
220
+ function addDiscriminatorProperty(
221
+ objectSchema: ObjectSchema,
222
+ properties: PropertySignatureStructure[]
223
+ ): PropertySignatureStructure[] {
224
+ const polymorphicProperty = getDiscriminatorProperty(objectSchema);
225
+
226
+ if (polymorphicProperty) {
227
+ // It is possible that the polymorphic property needs to override an existing property.
228
+ // This is usually the case on the top level parent where the property already has a type of string
229
+ // we need to replace it with the polymorphic values of its children
230
+ const filteredProperties = properties.filter(
231
+ (p) => p.name !== polymorphicProperty.name
232
+ );
233
+ return [...filteredProperties, polymorphicProperty];
234
+ }
235
+
236
+ return properties;
237
+ }
238
+
239
+ /**
240
+ * Finds the name of the property used as discriminator and the discriminator value.
241
+ */
242
+ function getDiscriminatorProperty(
243
+ objectSchema: ObjectSchema
244
+ ): PropertySignatureStructure | undefined {
245
+ const discriminatorValue = objectSchema.discriminatorValue;
246
+ if (!discriminatorValue && !objectSchema.discriminator) {
247
+ return undefined;
248
+ }
249
+
250
+ const discriminators = getDiscriminatorValue(objectSchema);
251
+ const discriminatorPropertyName = getDiscriminatorPropertyName(objectSchema);
252
+
253
+ if (discriminators) {
254
+ if (discriminatorPropertyName === undefined) {
255
+ throw new Error(
256
+ `getDiscriminatorProperty: Expected object ${objectSchema.name} to have a discriminator in its hierarchy but found none`
257
+ );
258
+ }
259
+
260
+ return {
261
+ kind: StructureKind.PropertySignature,
262
+ name: `"${discriminatorPropertyName}"`,
263
+ type: discriminators
264
+ };
265
+ }
266
+
267
+ return undefined;
268
+ }
269
+
270
+ /**
271
+ * Finds the closest discriminator property
272
+ */
273
+ function getDiscriminatorPropertyName(objectSchema: ObjectSchema) {
274
+ if (objectSchema.discriminator !== undefined) {
275
+ return objectSchema.discriminator.name;
276
+ }
277
+
278
+ const allParents = objectSchema.parents?.all ?? [];
279
+
280
+ for (const parent of allParents) {
281
+ if (isObjectSchema(parent) && parent.discriminator) {
282
+ return parent.discriminator.name;
283
+ }
284
+ }
285
+ return undefined;
286
+ }
287
+
288
+ /**
289
+ * Calculates the discriminator values that a given object needs
290
+ */
291
+ function getDiscriminatorValue(objectSchema: ObjectSchema): string | undefined {
292
+ const discriminatorValue = objectSchema.discriminatorValue
293
+ ? objectSchema.discriminatorValue
294
+ : objectSchema.discriminator
295
+ ? objectSchema.name
296
+ : undefined;
297
+ const children = objectSchema.children?.immediate ?? [];
298
+
299
+ // If the current object has a discriminatorValue but doesn't have any children
300
+ // it is a leaf node and the only discriminator value needed is itself
301
+ if (discriminatorValue && !children.length) {
302
+ return `"${discriminatorValue}"`;
303
+ }
304
+
305
+ // when the current object has both discriminator and discriminatorValue
306
+ if (children) {
307
+ const discriminatorProperty = objectSchema.discriminator;
308
+ // Even when there are children, if no discriminatorProperty is present this is a leaf in the polymorphism tree
309
+ if (!discriminatorProperty) {
310
+ return `"${discriminatorValue}"`;
311
+ }
312
+
313
+ // the current object has discriminated children we need to find all the discriminatorValues for each of its children
314
+ const allChildren = objectSchema.children?.all ?? [];
315
+
316
+ // Top level parents may not have a discriminator of their own.
317
+ const selfDiscriminator = discriminatorValue
318
+ ? [`"${discriminatorValue}"`]
319
+ : [];
320
+
321
+ const childValues = getChildDiscriminatorValues(allChildren).map(
322
+ (v) => `"${v}"`
323
+ );
324
+
325
+ return [...selfDiscriminator, ...childValues].join(" | ");
326
+ }
327
+
328
+ return undefined;
329
+ }
330
+
331
+ /**
332
+ * Looks into the children and grabs all possible discriminatorValues
333
+ */
334
+ function getChildDiscriminatorValues(children: ObjectSchema[]): string[] {
335
+ const discriminatorValues = new Set<string>();
336
+ for (const child of children) {
337
+ if (isObjectSchema(child) && child.discriminatorValue) {
338
+ discriminatorValues.add(child.discriminatorValue);
339
+ }
340
+ }
341
+
342
+ return [...discriminatorValues];
343
+ }
344
+
345
+ /**
346
+ * Gets a list of types a given object may extend from
347
+ */
348
+ function getImmediateParentsNames(
349
+ objectSchema: ObjectSchema,
350
+ schemaUsage: SchemaContext[]
351
+ ): string[] {
352
+ if (!objectSchema.parents?.immediate) {
353
+ return [];
354
+ }
355
+
356
+ const extendFrom: string[] = [];
357
+
358
+ // If an immediate parent is a DictionarySchema, that means that the object has been marked
359
+ // with additional properties. We need to add Record<string, unknown> to the extend list and
360
+ if (objectSchema.parents.immediate.find(isDictionarySchema)) {
361
+ extendFrom.push("Record<string, unknown>");
362
+ }
363
+
364
+ // Get the rest of the parents excluding any DictionarySchemas
365
+ const parents = objectSchema.parents.immediate
366
+ .filter((p) => !isDictionarySchema(p))
367
+ .map((parent) => {
368
+ const nameSuffix = schemaUsage.includes(SchemaContext.Output)
369
+ ? "Output"
370
+ : "";
371
+ const name = `${normalizeName(
372
+ parent.name,
373
+ NameType.Interface,
374
+ true /** shouldGuard */
375
+ )}${nameSuffix}`;
376
+
377
+ return isObjectSchema(parent) && isPolymorphicParent(parent)
378
+ ? `${name}Parent`
379
+ : name;
380
+ });
381
+
382
+ return [...parents, ...extendFrom];
383
+ }
384
+
385
+ function getPropertySignatures(
386
+ properties: { [key: string]: Property },
387
+ schemaUsage: SchemaContext[],
388
+ importedModels: Set<string>
389
+ ) {
390
+ let validProperties = Object.keys(properties);
391
+ const readOnlyFilter = (name: string) =>
392
+ !(schemaUsage.includes(SchemaContext.Input) && properties[name].readOnly);
393
+ const neverFilter = (name: string) => properties[name].type !== "never";
394
+ validProperties = validProperties.filter(readOnlyFilter).filter(neverFilter);
395
+ return validProperties.map((p) =>
396
+ getPropertySignature(
397
+ { ...properties[p], name: p },
398
+ schemaUsage,
399
+ importedModels
400
+ )
401
+ );
402
+ }
403
+
404
+ /**
405
+ * Builds a Typescript property or parameter signature
406
+ * @param property - Property or parameter to get the Typescript signature for
407
+ * @param importedModels - Set to track the models that need to be imported
408
+ * @returns a PropertySignatureStructure for the property.
409
+ */
410
+ export function getPropertySignature(
411
+ property: Property | Parameter,
412
+ schemaUsage: SchemaContext[],
413
+ importedModels: Set<string>
414
+ ): PropertySignatureStructure {
415
+ const propertyName = property.name;
416
+
417
+ const description = property.description;
418
+ let type =
419
+ generateForOutput(schemaUsage, property.usage) && property.outputTypeName
420
+ ? property.outputTypeName
421
+ : property.typeName
422
+ ? property.typeName
423
+ : property.type;
424
+ if (property.typeName && property.fromCore) {
425
+ importedModels.add(property.typeName);
426
+ type = property.typeName;
427
+ }
428
+ return {
429
+ name: propertyName,
430
+ ...(description && { docs: [{ description }] }),
431
+ hasQuestionToken: !property.required,
432
+ isReadonly:
433
+ generateForOutput(schemaUsage, property.usage) && property.readOnly,
434
+ type,
435
+ kind: StructureKind.PropertySignature
436
+ };
437
+ }
438
+
439
+ function generateForOutput(
440
+ schemaUsage: SchemaContext[],
441
+ propertyUsage?: SchemaContext[]
442
+ ) {
443
+ return (
444
+ (schemaUsage.includes(SchemaContext.Output) &&
445
+ propertyUsage?.includes(SchemaContext.Output)) ||
446
+ (schemaUsage.includes(SchemaContext.Exception) &&
447
+ propertyUsage?.includes(SchemaContext.Exception))
448
+ );
449
+ }
@@ -0,0 +1,33 @@
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 { paginateContent } from "./static/paginateContent.js";
6
+
7
+ export function buildPaginateHelper(model: RLCModel) {
8
+ const pagingInfo = model.annotations;
9
+ // return directly if no paging info
10
+ if (!pagingInfo || pagingInfo.hasPaging !== true || !pagingInfo.pageDetails) {
11
+ return;
12
+ }
13
+
14
+ hbs.registerHelper(
15
+ "quoteWrap",
16
+ function (value: string | number | boolean | string[]) {
17
+ if (Array.isArray(value)) {
18
+ return value.map((element) => `"${element}"`).join();
19
+ }
20
+
21
+ return `"${value}"`;
22
+ }
23
+ );
24
+
25
+ const { srcPath } = model;
26
+ const paginateHelperContents = hbs.compile(paginateContent, {
27
+ noEscape: true
28
+ });
29
+ return {
30
+ path: path.join(srcPath, "paginateHelper.ts"),
31
+ content: paginateHelperContents(pagingInfo.pageDetails)
32
+ };
33
+ }