@azure-tools/typespec-ts 0.36.0 → 0.37.0-alpha.20241230.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 (146) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/src/contextManager.d.ts +1 -2
  3. package/dist/src/contextManager.d.ts.map +1 -1
  4. package/dist/src/contextManager.js.map +1 -1
  5. package/dist/src/framework/load-static-helpers.d.ts +2 -1
  6. package/dist/src/framework/load-static-helpers.d.ts.map +1 -1
  7. package/dist/src/framework/load-static-helpers.js +17 -0
  8. package/dist/src/framework/load-static-helpers.js.map +1 -1
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/index.js +31 -29
  11. package/dist/src/index.js.map +1 -1
  12. package/dist/src/lib.js +1 -1
  13. package/dist/src/lib.js.map +1 -1
  14. package/dist/src/metaTree.d.ts +0 -5
  15. package/dist/src/metaTree.d.ts.map +1 -1
  16. package/dist/src/modular/buildClassicalClient.d.ts +3 -2
  17. package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
  18. package/dist/src/modular/buildClassicalClient.js +64 -62
  19. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  20. package/dist/src/modular/buildClassicalOperationGroups.d.ts +3 -2
  21. package/dist/src/modular/buildClassicalOperationGroups.d.ts.map +1 -1
  22. package/dist/src/modular/buildClassicalOperationGroups.js +35 -27
  23. package/dist/src/modular/buildClassicalOperationGroups.js.map +1 -1
  24. package/dist/src/modular/buildClientContext.d.ts +4 -3
  25. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  26. package/dist/src/modular/buildClientContext.js +84 -35
  27. package/dist/src/modular/buildClientContext.js.map +1 -1
  28. package/dist/src/modular/buildModularOptions.d.ts +7 -0
  29. package/dist/src/modular/buildModularOptions.d.ts.map +1 -0
  30. package/dist/src/modular/buildModularOptions.js +16 -0
  31. package/dist/src/modular/buildModularOptions.js.map +1 -0
  32. package/dist/src/modular/buildOperations.d.ts +6 -4
  33. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  34. package/dist/src/modular/buildOperations.js +56 -55
  35. package/dist/src/modular/buildOperations.js.map +1 -1
  36. package/dist/src/modular/buildProjectFiles.d.ts +3 -2
  37. package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
  38. package/dist/src/modular/buildProjectFiles.js +18 -16
  39. package/dist/src/modular/buildProjectFiles.js.map +1 -1
  40. package/dist/src/modular/buildRestorePoller.d.ts +4 -2
  41. package/dist/src/modular/buildRestorePoller.d.ts.map +1 -1
  42. package/dist/src/modular/buildRestorePoller.js +22 -18
  43. package/dist/src/modular/buildRestorePoller.js.map +1 -1
  44. package/dist/src/modular/buildRootIndex.d.ts +4 -3
  45. package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
  46. package/dist/src/modular/buildRootIndex.js +40 -31
  47. package/dist/src/modular/buildRootIndex.js.map +1 -1
  48. package/dist/src/modular/buildSubpathIndex.d.ts +4 -2
  49. package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
  50. package/dist/src/modular/buildSubpathIndex.js +8 -5
  51. package/dist/src/modular/buildSubpathIndex.js.map +1 -1
  52. package/dist/src/modular/emitLoggerFile.d.ts +2 -3
  53. package/dist/src/modular/emitLoggerFile.d.ts.map +1 -1
  54. package/dist/src/modular/emitLoggerFile.js +4 -4
  55. package/dist/src/modular/emitLoggerFile.js.map +1 -1
  56. package/dist/src/modular/emitModels.d.ts +1 -2
  57. package/dist/src/modular/emitModels.d.ts.map +1 -1
  58. package/dist/src/modular/emitModels.js +10 -3
  59. package/dist/src/modular/emitModels.js.map +1 -1
  60. package/dist/src/modular/emitModelsOptions.d.ts +3 -24
  61. package/dist/src/modular/emitModelsOptions.d.ts.map +1 -1
  62. package/dist/src/modular/emitModelsOptions.js +10 -86
  63. package/dist/src/modular/emitModelsOptions.js.map +1 -1
  64. package/dist/src/modular/emitSamples.js +2 -1
  65. package/dist/src/modular/emitSamples.js.map +1 -1
  66. package/dist/src/modular/helpers/classicalOperationHelpers.d.ts +3 -3
  67. package/dist/src/modular/helpers/classicalOperationHelpers.d.ts.map +1 -1
  68. package/dist/src/modular/helpers/classicalOperationHelpers.js +40 -50
  69. package/dist/src/modular/helpers/classicalOperationHelpers.js.map +1 -1
  70. package/dist/src/modular/helpers/clientHelpers.d.ts +11 -8
  71. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  72. package/dist/src/modular/helpers/clientHelpers.js +87 -60
  73. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  74. package/dist/src/modular/helpers/namingHelpers.d.ts +4 -7
  75. package/dist/src/modular/helpers/namingHelpers.d.ts.map +1 -1
  76. package/dist/src/modular/helpers/namingHelpers.js +3 -26
  77. package/dist/src/modular/helpers/namingHelpers.js.map +1 -1
  78. package/dist/src/modular/helpers/operationHelpers.d.ts +21 -20
  79. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  80. package/dist/src/modular/helpers/operationHelpers.js +336 -291
  81. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  82. package/dist/src/modular/helpers/typeHelpers.d.ts +4 -25
  83. package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
  84. package/dist/src/modular/helpers/typeHelpers.js +6 -218
  85. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  86. package/dist/src/modular/interfaces.d.ts +15 -8
  87. package/dist/src/modular/interfaces.d.ts.map +1 -1
  88. package/dist/src/modular/serialization/buildDeserializerFunction.d.ts.map +1 -1
  89. package/dist/src/modular/serialization/buildDeserializerFunction.js +1 -2
  90. package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -1
  91. package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -1
  92. package/dist/src/modular/serialization/buildSerializerFunction.js +1 -2
  93. package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
  94. package/dist/src/modular/serialization/serializeUtils.d.ts +8 -5
  95. package/dist/src/modular/serialization/serializeUtils.d.ts.map +1 -1
  96. package/dist/src/modular/serialization/serializeUtils.js +22 -22
  97. package/dist/src/modular/serialization/serializeUtils.js.map +1 -1
  98. package/dist/src/utils/clientUtils.d.ts +3 -1
  99. package/dist/src/utils/clientUtils.d.ts.map +1 -1
  100. package/dist/src/utils/clientUtils.js +10 -0
  101. package/dist/src/utils/clientUtils.js.map +1 -1
  102. package/dist/src/utils/operationUtil.d.ts +6 -2
  103. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  104. package/dist/src/utils/operationUtil.js +66 -7
  105. package/dist/src/utils/operationUtil.js.map +1 -1
  106. package/dist/tsconfig.tsbuildinfo +1 -1
  107. package/package.json +3 -3
  108. package/src/contextManager.ts +1 -2
  109. package/src/framework/load-static-helpers.ts +24 -1
  110. package/src/index.ts +65 -37
  111. package/src/lib.ts +1 -1
  112. package/src/metaTree.ts +0 -6
  113. package/src/modular/buildClassicalClient.ts +97 -99
  114. package/src/modular/buildClassicalOperationGroups.ts +53 -47
  115. package/src/modular/buildClientContext.ts +101 -44
  116. package/src/modular/buildModularOptions.ts +27 -0
  117. package/src/modular/buildOperations.ts +91 -78
  118. package/src/modular/buildProjectFiles.ts +24 -21
  119. package/src/modular/buildRestorePoller.ts +39 -23
  120. package/src/modular/buildRootIndex.ts +51 -42
  121. package/src/modular/buildSubpathIndex.ts +16 -7
  122. package/src/modular/emitLoggerFile.ts +12 -10
  123. package/src/modular/emitModels.ts +15 -7
  124. package/src/modular/emitModelsOptions.ts +18 -125
  125. package/src/modular/emitSamples.ts +2 -3
  126. package/src/modular/helpers/classicalOperationHelpers.ts +50 -75
  127. package/src/modular/helpers/clientHelpers.ts +107 -73
  128. package/src/modular/helpers/namingHelpers.ts +6 -65
  129. package/src/modular/helpers/operationHelpers.ts +506 -384
  130. package/src/modular/helpers/typeHelpers.ts +11 -267
  131. package/src/modular/interfaces.ts +16 -8
  132. package/src/modular/serialization/buildDeserializerFunction.ts +1 -6
  133. package/src/modular/serialization/buildSerializerFunction.ts +1 -2
  134. package/src/modular/serialization/serializeUtils.ts +31 -30
  135. package/src/utils/clientUtils.ts +23 -1
  136. package/src/utils/operationUtil.ts +106 -14
  137. package/dist/src/modular/buildCodeModel.d.ts +0 -34
  138. package/dist/src/modular/buildCodeModel.d.ts.map +0 -1
  139. package/dist/src/modular/buildCodeModel.js +0 -1489
  140. package/dist/src/modular/buildCodeModel.js.map +0 -1
  141. package/dist/src/modular/modularCodeModel.d.ts +0 -166
  142. package/dist/src/modular/modularCodeModel.d.ts.map +0 -1
  143. package/dist/src/modular/modularCodeModel.js +0 -2
  144. package/dist/src/modular/modularCodeModel.js.map +0 -1
  145. package/src/modular/buildCodeModel.ts +0 -1965
  146. package/src/modular/modularCodeModel.ts +0 -211
@@ -1,1965 +0,0 @@
1
- import {
2
- Enum,
3
- EnumMember,
4
- IntrinsicScalarName,
5
- Model,
6
- ModelProperty,
7
- Namespace,
8
- NoTarget,
9
- Operation,
10
- Program,
11
- Scalar,
12
- Type,
13
- Union,
14
- UsageFlags,
15
- getDiscriminator,
16
- getDoc,
17
- getEncode,
18
- getFriendlyName,
19
- getMaxItems,
20
- getMaxLength,
21
- getMaxValue,
22
- getMinItems,
23
- getMinLength,
24
- getMinValue,
25
- getPattern,
26
- getPropertyType,
27
- getSummary,
28
- getVisibility,
29
- isErrorModel,
30
- isNeverType,
31
- isNullType,
32
- isNumericType,
33
- isStringType,
34
- isTemplateDeclarationOrInstance,
35
- isType,
36
- isVoidType,
37
- listServices
38
- } from "@typespec/compiler";
39
- import {
40
- Header,
41
- Client as HrlcClient,
42
- Operation as HrlcOperation,
43
- Type as HrlcType,
44
- ModularCodeModel,
45
- OperationGroup,
46
- Parameter,
47
- Property,
48
- Response
49
- } from "./modularCodeModel.js";
50
- import {
51
- HttpAuth,
52
- HttpOperation,
53
- HttpOperationParameter,
54
- HttpOperationResponse,
55
- HttpOperationResponseContent,
56
- HttpServer,
57
- getAuthentication,
58
- getServers,
59
- isSharedRoute
60
- } from "@typespec/http";
61
- import {
62
- NameType,
63
- RLCModel,
64
- buildRuntimeImports,
65
- isAzurePackage,
66
- normalizeName
67
- } from "@azure-tools/rlc-common";
68
- import {
69
- SdkBuiltInType,
70
- SdkClient,
71
- SdkType,
72
- getAllModels,
73
- getClientNamespaceString,
74
- getClientType,
75
- getDefaultApiVersion,
76
- getHttpOperationWithCache,
77
- getLibraryName,
78
- getSdkUnion,
79
- getWireName,
80
- isApiVersion,
81
- listClients,
82
- listOperationGroups,
83
- listOperationsInOperationGroup
84
- } from "@azure-tools/typespec-client-generator-core";
85
- import {
86
- buildCoreTypeInfo,
87
- getBodyType,
88
- getDefaultApiVersionString,
89
- getEffectiveSchemaType,
90
- isAzureCoreErrorType,
91
- isBodyRequired,
92
- isSchemaProperty
93
- } from "../utils/modelUtils.js";
94
- import { camelToSnakeCase, toCamelCase } from "../utils/casingUtils.js";
95
- import {
96
- extractPagedMetadataNested,
97
- getOperationGroupName,
98
- getOperationName,
99
- isBinaryPayload,
100
- isIgnoredHeaderParam,
101
- isLongRunningOperation,
102
- parseItemName,
103
- parseNextLinkName
104
- } from "../utils/operationUtil.js";
105
- import {
106
- getLroMetadata,
107
- getPagedResult,
108
- LroMetadata
109
- } from "@azure-tools/typespec-azure-core";
110
-
111
- import { Project } from "ts-morph";
112
- import { SdkContext } from "../utils/interfaces.js";
113
- import { getAddedOnVersions } from "@typespec/versioning";
114
- import { getModelNamespaceName } from "../utils/namespaceUtils.js";
115
- import { getSupportedHttpAuth } from "../utils/credentialUtils.js";
116
- import { getType as getTypeName } from "./helpers/typeHelpers.js";
117
- import { reportDiagnostic } from "../lib.js";
118
- import { useContext } from "../contextManager.js";
119
- import { normalizeModelName } from "./emitModels.js";
120
-
121
- interface HttpServerParameter {
122
- type: "endpointPath";
123
- name: string;
124
- param: ModelProperty;
125
- }
126
-
127
- interface CredentialType {
128
- kind: "Credential";
129
- scheme: HttpAuth;
130
- }
131
-
132
- interface CredentialTypeUnion {
133
- kind: "CredentialTypeUnion";
134
- types: CredentialType[];
135
- }
136
-
137
- type EmitterType = Type | CredentialType | CredentialTypeUnion;
138
-
139
- let CASING: "camel" | "snake" = "snake";
140
-
141
- export interface EmitterOptions {
142
- "basic-setup-py"?: boolean;
143
- "package-version"?: string;
144
- "package-name"?: string;
145
- "output-dir"?: string;
146
- "package-mode"?: string;
147
- debug?: boolean;
148
- }
149
-
150
- function applyCasing(
151
- name: string,
152
- options: { casing: "snake" | "camel" } = { casing: "snake" }
153
- ): string {
154
- if (options.casing === "camel") {
155
- return toCamelCase(name);
156
- }
157
-
158
- return camelToSnakeCase(name);
159
- }
160
-
161
- const typesMap = new Map<EmitterType, HrlcType>();
162
- const simpleTypesMap = new Map<string, HrlcType>();
163
- const endpointPathParameters: Record<string, any>[] = [];
164
- let methodApiVersionParam: Parameter | undefined = undefined;
165
- let serverApiVersionParam: Parameter | undefined = undefined;
166
-
167
- function isSimpleType(
168
- program: Program,
169
- type: EmitterType | undefined
170
- ): boolean {
171
- // these decorators can only work for simple type(int/string/float, etc)
172
- if (type && (type.kind === "Scalar" || type.kind === "ModelProperty")) {
173
- const funcs = [
174
- getMinValue,
175
- getMaxValue,
176
- getMinLength,
177
- getMaxLength,
178
- getPattern,
179
- getEncode
180
- ];
181
- for (const func of funcs) {
182
- if (func(program, type)) {
183
- return true;
184
- }
185
- }
186
- }
187
- return false;
188
- }
189
-
190
- function getDocStr(program: Program, target: Type): string {
191
- return getDoc(program, target) ?? "";
192
- }
193
-
194
- function isDiscriminator(
195
- context: SdkContext,
196
- type: Model,
197
- propertyName: string
198
- ): boolean {
199
- const discriminator = getDiscriminator(context.program, type);
200
- if (discriminator && discriminator.propertyName === propertyName) {
201
- return true;
202
- }
203
- return false;
204
- }
205
-
206
- function handleDiscriminator(
207
- context: SdkContext,
208
- type: Model,
209
- usage: UsageFlags
210
- ) {
211
- const discriminator = getDiscriminator(context.program, type);
212
- if (discriminator) {
213
- const discriminatorValues: string[] = [];
214
- const aliases: string[] = [];
215
- const discriminatedSubtypes: Type[] = [];
216
- let discriminatorTcgcType = undefined;
217
- for (const childModel of type.derivedModels) {
218
- const modelType = getType(context, childModel, { usage });
219
- aliases.push(modelType.name);
220
- for (const property of modelType.properties) {
221
- if (property.restApiName === discriminator.propertyName) {
222
- modelType.discriminatorValue = property.type.value;
223
- discriminatorValues.push(modelType.discriminatorValue);
224
- discriminatorTcgcType = getClientType(context, property.type);
225
- }
226
- }
227
- discriminatedSubtypes.push(modelType);
228
- }
229
- const discriminatorInfo = {
230
- description:
231
- discriminatorValues.length > 0
232
- ? `the discriminator possible values: ${discriminatorValues.join(
233
- ", "
234
- )}`
235
- : "discriminator property",
236
- type: { type: "string", tcgcType: discriminatorTcgcType },
237
- restApiName: discriminator.propertyName,
238
- clientName: discriminator.propertyName,
239
- name: discriminator.propertyName,
240
- isPolymorphic: true,
241
- isDiscriminator: true,
242
- aliases,
243
- discriminatedSubtypes
244
- };
245
- return discriminatorInfo;
246
- }
247
- return undefined;
248
- }
249
-
250
- function processModelProperties(
251
- context: SdkContext,
252
- newValue: any,
253
- model: Model,
254
- usage: UsageFlags
255
- ) {
256
- // need to do properties after insertion to avoid infinite recursion
257
- const discriminatorInfo = handleDiscriminator(context, model, usage);
258
- let hasDiscriminator = false;
259
- for (const property of model.properties.values()) {
260
- if (!isSchemaProperty(context.program, property)) {
261
- continue;
262
- }
263
- if (isNeverType(property.type)) {
264
- continue;
265
- }
266
- if (newValue.properties === undefined || newValue.properties === null) {
267
- newValue.properties = [];
268
- }
269
- let newProperty = emitProperty(context, property, usage);
270
- if (isDiscriminator(context, model, property.name)) {
271
- hasDiscriminator = true;
272
- newProperty = {
273
- ...newProperty,
274
- ...discriminatorInfo,
275
- type: newProperty["type"],
276
- tcgcType: getClientType(context, property)
277
- };
278
- }
279
- newValue.properties.push(newProperty);
280
- }
281
- if (discriminatorInfo) {
282
- if (!hasDiscriminator) {
283
- newValue.properties.push({ ...discriminatorInfo });
284
- }
285
- // we don't need to add the discriminator info if it's an anonymous model
286
- // because it's impossible to have a anonymous model as the polymorphic base in typespec
287
- // the only possibility is the anonymous model is an alias for an union type which has already been taken care of in the combined types.
288
- if (newValue.name) {
289
- newValue.name = normalizeName(newValue.name, NameType.Interface);
290
- discriminatorInfo?.aliases.push(`${newValue.name}`);
291
- newValue.alias = `${newValue.name.replace(/Union$/g, "")}`;
292
- newValue.name = `${newValue.name}`;
293
- newValue.aliasType = discriminatorInfo?.aliases.join(" | ");
294
- newValue.types = discriminatorInfo?.discriminatedSubtypes;
295
- newValue.isPolymorphicBaseModel = true;
296
- newValue.discriminator = discriminatorInfo.restApiName;
297
- }
298
- }
299
- }
300
-
301
- function isEmptyAnonymousModel(type: EmitterType): boolean {
302
- // object, {}, all will be treated as empty model
303
- return (
304
- type.kind === "Model" &&
305
- type.name === "" &&
306
- type.properties.size === 0 &&
307
- !type.baseModel &&
308
- type.derivedModels.length === 0 &&
309
- !type.indexer
310
- );
311
- }
312
-
313
- interface EmitTypeOptions {
314
- disableEffectiveModel?: boolean;
315
- usage?: UsageFlags;
316
- }
317
-
318
- export function getType(
319
- context: SdkContext,
320
- type: EmitterType,
321
- options: EmitTypeOptions = {}
322
- ): any {
323
- const modularMetatree = useContext("modularMetaTree");
324
-
325
- // don't cache simple type(string, int, etc) since decorators may change the result
326
- const enableCache = !isSimpleType(context.program, type);
327
- const effectiveModel =
328
- !options.disableEffectiveModel &&
329
- (type.kind === "Model" || type.kind === "Union")
330
- ? getEffectiveSchemaType(context.program, type)
331
- : type;
332
- if (enableCache) {
333
- const cached = typesMap.get(effectiveModel);
334
- if (cached) {
335
- return cached;
336
- }
337
- }
338
- let newValue: any = { __raw: type };
339
-
340
- if (isEmptyAnonymousModel(type)) {
341
- // do not generate model for empty model, treat it as any
342
- newValue = { type: "any" };
343
- } else {
344
- newValue = emitType(context, type, options);
345
- }
346
- if (type.kind === "ModelProperty" || type.kind === "Scalar") {
347
- newValue = applyEncoding(context.program, type, newValue);
348
- }
349
-
350
- if (isTypespecType(type)) {
351
- newValue.tcgcType = getClientType(context, effectiveModel as any);
352
- newValue.name = !newValue.tcgcType.isGeneratedName
353
- ? normalizeModelName(context, newValue.tcgcType)
354
- : newValue.name;
355
- newValue.__raw = type;
356
- modularMetatree.set(type, newValue);
357
- }
358
-
359
- if (enableCache) {
360
- if (!options.disableEffectiveModel) {
361
- if (newValue.__raw === undefined) {
362
- newValue.__raw = type;
363
- }
364
- typesMap.set(effectiveModel, newValue);
365
- }
366
- if (type.kind === "Union") {
367
- for (const t of type.variants.values()) {
368
- if (t.type.kind === "Model") {
369
- processModelProperties(context, newValue, t.type, options.usage!);
370
- }
371
- }
372
- }
373
- if (type.kind === "Model") {
374
- // need to do properties after insertion to avoid infinite recursion
375
- processModelProperties(context, newValue, type, options.usage!);
376
- if (newValue.type === "dict") {
377
- newValue = { ...emitModel(context, type, options), ...newValue };
378
- typesMap.set(effectiveModel, newValue);
379
- }
380
- }
381
- } else {
382
- const { __raw, tcgcType, ...keyableValue } = newValue;
383
- const key = JSON.stringify(keyableValue);
384
- const value = simpleTypesMap.get(key);
385
- if (value) {
386
- newValue = value;
387
- } else {
388
- simpleTypesMap.set(key, newValue);
389
- }
390
- }
391
- if (
392
- type.kind === "Model" &&
393
- newValue.tcgcType.additionalProperties &&
394
- !context.rlcOptions?.compatibilityMode
395
- ) {
396
- reportDiagnostic(context.program, {
397
- code: "compatible-additional-properties",
398
- format: {
399
- modelName: type?.name ?? ""
400
- },
401
- target: type
402
- });
403
- }
404
-
405
- typesMap.set(effectiveModel, newValue);
406
- return newValue;
407
- }
408
-
409
- function isTypespecType(type: EmitterType): type is Type {
410
- return type.kind !== "Credential" && type.kind !== "CredentialTypeUnion";
411
- }
412
-
413
- // To pass the yaml dump
414
- function getAddedOnVersion(p: Program, t: Type): string | undefined {
415
- return getAddedOnVersions(p, t)?.[0]?.value;
416
- }
417
-
418
- type ParamBase = {
419
- optional: boolean;
420
- description: string;
421
- addedOn: string | undefined;
422
- clientName: string;
423
- restApiName: string;
424
- inOverload: boolean;
425
- format?: string;
426
- tcgcType: SdkType;
427
- };
428
- function emitParamBase(
429
- context: SdkContext,
430
- parameter: ModelProperty | Type
431
- ): ParamBase {
432
- let optional: boolean;
433
- let name: string;
434
- let restApiName: string;
435
- let description: string = "";
436
- let addedOn: string | undefined;
437
- let format: string | undefined;
438
-
439
- const program = context.program;
440
-
441
- if (parameter.kind === "ModelProperty") {
442
- optional = parameter.optional;
443
- name = normalizeName(
444
- getLibraryName(context, parameter),
445
- NameType.Parameter,
446
- true
447
- );
448
- restApiName = getWireName(context, parameter);
449
- description = getDocStr(program, parameter);
450
- addedOn = getAddedOnVersion(program, parameter);
451
- const newParameter = applyEncoding(program, parameter, parameter);
452
- format = newParameter.format;
453
- } else {
454
- optional = false;
455
- name = "body";
456
- restApiName = "body";
457
- }
458
-
459
- return {
460
- optional,
461
- description,
462
- addedOn,
463
- clientName: applyCasing(name, { casing: CASING }),
464
- restApiName,
465
- inOverload: false,
466
- format,
467
- tcgcType: getClientType(context, parameter)
468
- };
469
- }
470
-
471
- type BodyParameter = ParamBase & {
472
- contentTypes: string[];
473
- type: Type;
474
- location: "body";
475
- // defaultContentType: string;
476
- isBinaryPayload: boolean;
477
- };
478
-
479
- function emitBodyParameter(
480
- context: SdkContext,
481
- httpOperation: HttpOperation
482
- ): BodyParameter | undefined {
483
- const params = httpOperation.parameters;
484
- const body = params.body!;
485
- if (body.bodyKind === "single") {
486
- const base = emitParamBase(context, body.parameter ?? body.type);
487
- let contentTypes = body.contentTypes;
488
- if (contentTypes.length === 0) {
489
- contentTypes = ["application/json"];
490
- }
491
- const type = getType(context, getBodyType(httpOperation)!, {
492
- disableEffectiveModel: true,
493
- usage: UsageFlags.Input
494
- });
495
-
496
- return {
497
- contentTypes,
498
- type,
499
- location: "body",
500
- ...base,
501
- isBinaryPayload: isBinaryPayload(context, body.type, contentTypes),
502
- optional: !isBodyRequired(httpOperation.parameters)
503
- };
504
- }
505
- return undefined;
506
- }
507
-
508
- function emitParameter(
509
- context: SdkContext,
510
- parameter: HttpOperationParameter | HttpServerParameter,
511
- implementation: string
512
- ): Parameter | undefined {
513
- if (parameter.type === "cookie") {
514
- // TODO: support cookie parameters, https://github.com/Azure/autorest.typescript/issues/2898
515
- reportDiagnostic(context.program, {
516
- code: "parameter-type-not-supported",
517
- format: {
518
- paramType: parameter.type,
519
- paramName: parameter.name
520
- },
521
- target: NoTarget
522
- });
523
- return undefined;
524
- }
525
- const base = emitParamBase(context, parameter.param);
526
- let type = getType(context, parameter.param.type, {
527
- usage: UsageFlags.Input
528
- });
529
- let clientDefaultValue = undefined;
530
- if (
531
- parameter.name.toLowerCase() === "content-type" &&
532
- type["type"] === "constant"
533
- ) {
534
- /// We don't want constant types for content types, so we make sure if it's
535
- /// a constant, we make it not constant
536
- clientDefaultValue = type["value"];
537
- type = {
538
- ...type["valueType"],
539
- tcgcType:
540
- base.tcgcType.kind === "constant"
541
- ? base.tcgcType.valueType
542
- : base.tcgcType
543
- };
544
- }
545
- const paramMap = {
546
- restApiName: parameter.name,
547
- location: parameter.type,
548
- type: base.format ? { ...type, format: base.format } : type,
549
- implementation: implementation,
550
- skipUrlEncoding:
551
- parameter.type === "endpointPath" ||
552
- (parameter.type === "path" && parameter.allowReserved),
553
- format: (parameter as any).format ?? base.format,
554
- tcgcType: base.tcgcType
555
- };
556
-
557
- if (paramMap.type.type === "constant") {
558
- clientDefaultValue = paramMap.type.value;
559
- }
560
-
561
- if (
562
- isApiVersion(context, parameter as HttpOperationParameter) &&
563
- (paramMap.location === "query" || paramMap.location === "endpointPath")
564
- ) {
565
- const defaultApiVersion = getDefaultApiVersion(
566
- context,
567
- getServiceNamespace(context.program)
568
- );
569
- paramMap.implementation = implementation;
570
- (paramMap as any).in_docstring = false;
571
- if (defaultApiVersion) {
572
- clientDefaultValue = defaultApiVersion.value;
573
- }
574
- if (!clientDefaultValue) {
575
- clientDefaultValue = getDefaultApiVersionString(context);
576
- }
577
- if (clientDefaultValue !== undefined) {
578
- (paramMap as any).optional = true;
579
- }
580
- }
581
-
582
- if (
583
- clientDefaultValue === undefined &&
584
- paramMap.location === "endpointPath" &&
585
- parameter.param.defaultValue?.valueKind === "StringValue"
586
- ) {
587
- // For endpoint path params, treat the default value as a client default.
588
- clientDefaultValue = parameter.param.defaultValue.value;
589
- }
590
-
591
- return { clientDefaultValue, ...base, ...paramMap };
592
- }
593
-
594
- function emitFlattenedParameter(
595
- bodyParameter: Record<string, any>,
596
- property: any
597
- ): Record<string, any> {
598
- return {
599
- checkClientInput: false,
600
- clientDefaultValue: null,
601
- clientName: property.clientName,
602
- delimiter: null,
603
- description: property.description,
604
- implementation: "Method",
605
- inDocstring: true,
606
- inFlattenedBody: true,
607
- inOverload: false,
608
- inOverriden: false,
609
- isApiVersion: bodyParameter["isApiVersion"],
610
- location: "other",
611
- optional: property["optional"],
612
- restApiName: null,
613
- skipUrlEncoding: false,
614
- type: property["type"],
615
- defaultToUnsetSentinel: true
616
- };
617
- }
618
-
619
- function emitResponseHeaders(
620
- context: SdkContext,
621
- headers?: Record<string, ModelProperty>
622
- ): Header[] {
623
- const retval: Header[] = [];
624
- if (!headers) {
625
- return retval;
626
- }
627
- for (const [key, value] of Object.entries(headers)) {
628
- retval.push({
629
- type: getType(context, value.type, { usage: UsageFlags.Output }),
630
- restApiName: key
631
- });
632
- }
633
- return retval;
634
- }
635
-
636
- function emitResponse(
637
- context: SdkContext,
638
- operation: Operation,
639
- response: HttpOperationResponse,
640
- innerResponse: HttpOperationResponseContent
641
- ): Response {
642
- let type = undefined;
643
- if (
644
- innerResponse.body?.type &&
645
- !isAzureCoreErrorType(context.program, innerResponse.body?.type)
646
- ) {
647
- // temporary logic. It can be removed after compiler optimize the response
648
- const candidate = [
649
- "ResourceOkResponse",
650
- "ResourceCreatedResponse",
651
- "AcceptedResponse"
652
- ];
653
- const originType = innerResponse.body.type as Model;
654
- if (
655
- innerResponse.body.type.kind === "Model" &&
656
- candidate.find((e) => e === originType.name)
657
- ) {
658
- const modelType = getEffectiveSchemaType(context.program, originType);
659
- type = getType(context, modelType, { usage: UsageFlags.Output });
660
- } else if (isLroResponse()) {
661
- const metadata = getLroMetadata(context.program, operation);
662
- type =
663
- metadata?.finalResult === "void" || metadata?.finalResult === undefined
664
- ? undefined
665
- : getType(context, metadata.finalResult);
666
- } else {
667
- type = isVoidType(innerResponse.body.type)
668
- ? undefined
669
- : getType(context, innerResponse.body.type, {
670
- usage: UsageFlags.Output
671
- });
672
- }
673
- }
674
- const statusCodes: (number | "default")[] = [];
675
- if (response.statusCode === "*") {
676
- statusCodes.push("default");
677
- } else {
678
- statusCodes.push(parseInt(response.statusCode));
679
- }
680
- return {
681
- headers: emitResponseHeaders(context, innerResponse.headers),
682
- statusCodes: statusCodes ?? [],
683
- addedOn: getAddedOnVersion(context.program, response.type),
684
- discriminator: "basic",
685
- type: type,
686
- isBinaryPayload: innerResponse.body?.type
687
- ? isBinaryPayload(
688
- context,
689
- innerResponse.body?.type,
690
- innerResponse.body?.contentTypes![0] ?? "application/json"
691
- )
692
- : false
693
- };
694
-
695
- function isLroResponse() {
696
- return (
697
- typeof response.statusCodes === "number" &&
698
- ["200", "201", "202"]?.includes(`${response.statusCodes}`) &&
699
- !!getLroMetadata(context.program, operation)
700
- );
701
- }
702
- }
703
-
704
- function emitOperation(
705
- context: SdkContext,
706
- operation: Operation,
707
- operationGroupName: string,
708
- rlcModels: RLCModel,
709
- hierarchies: string[]
710
- ): HrlcOperation {
711
- const isAzureFlavor = isAzurePackage(rlcModels);
712
- const emittedOperation = emitBasicOperation(
713
- context,
714
- operation,
715
- operationGroupName,
716
- rlcModels,
717
- hierarchies
718
- );
719
- // Skip to extract paging and lro information for non-branded clients.
720
- if (!isAzureFlavor) {
721
- return emittedOperation;
722
- }
723
- const lro = isLongRunningOperation(
724
- context.program,
725
- getHttpOperationWithCache(context, operation)
726
- );
727
- const pagingMetadata = getPagedResult(context.program, operation);
728
- // Disable the paging feature if no itemsSegments is found.
729
- const paging =
730
- pagingMetadata &&
731
- pagingMetadata.itemsSegments &&
732
- pagingMetadata.itemsSegments.length > 0;
733
- if (
734
- pagingMetadata &&
735
- (!pagingMetadata.itemsSegments || pagingMetadata.itemsSegments.length === 0)
736
- ) {
737
- reportDiagnostic(context.program, {
738
- code: "no-paging-items-defined",
739
- format: {
740
- operationName: operation.name
741
- },
742
- target: operation
743
- });
744
- }
745
-
746
- emitExtraInfoForOperation(emittedOperation);
747
- return emittedOperation;
748
-
749
- function emitExtraInfoForOperation(emittedOperation: HrlcOperation) {
750
- if (lro) {
751
- addLroInformation(context, operation, emittedOperation);
752
- }
753
- if (paging) {
754
- addPagingInformation(context, operation, emittedOperation);
755
- }
756
- if (lro && paging) {
757
- emittedOperation["discriminator"] = "lropaging";
758
- }
759
- }
760
- }
761
-
762
- function addLroInformation(
763
- context: SdkContext,
764
- operation: Operation,
765
- emittedOperation: HrlcOperation
766
- ) {
767
- emittedOperation["discriminator"] = "lro";
768
- const metadata = getLroMetadata(context.program, operation);
769
- emittedOperation["lroMetadata"] = {
770
- finalResult:
771
- metadata?.finalResult === "void" || metadata?.finalResult === undefined
772
- ? undefined
773
- : getType(context, metadata.finalResult),
774
- finalStateVia: getFinalStateVia(context, operation, metadata),
775
- finalResultPath: metadata?.finalResultPath
776
- };
777
- }
778
-
779
- function getFinalStateVia(
780
- context: SdkContext,
781
- operation: Operation,
782
- metadata?: LroMetadata
783
- ) {
784
- if (!metadata) {
785
- return undefined;
786
- }
787
- switch (metadata.finalStateVia) {
788
- case "azure-async-operation":
789
- case "location":
790
- case "operation-location":
791
- case "original-uri":
792
- return metadata.finalStateVia;
793
- default:
794
- reportDiagnostic(context.program, {
795
- code: "un-supported-finalStateVia",
796
- format: {
797
- finalStateVia: metadata.finalStateVia!
798
- },
799
- target: operation
800
- });
801
- return undefined;
802
- }
803
- }
804
-
805
- function addPagingInformation(
806
- context: SdkContext,
807
- operation: Operation,
808
- emittedOperation: Record<string, any>
809
- ) {
810
- emittedOperation["discriminator"] = "paging";
811
- const pagedResult = getPagedResult(context.program, operation);
812
- if (pagedResult === undefined) {
813
- throw Error(
814
- "Trying to add paging information, but not paging metadata for this operation"
815
- );
816
- }
817
- emittedOperation["itemName"] = parseItemName(pagedResult);
818
- emittedOperation["continuationTokenName"] = parseNextLinkName(pagedResult);
819
- }
820
-
821
- function emitBasicOperation(
822
- context: SdkContext,
823
- operation: Operation,
824
- operationGroupName: string,
825
- rlcModels: RLCModel,
826
- hierarchies: string[]
827
- ): HrlcOperation {
828
- // Set up parameters for operation
829
- const parameters: any[] = [];
830
- if (endpointPathParameters) {
831
- for (const param of endpointPathParameters) {
832
- parameters.push(param);
833
- }
834
- }
835
- const httpOperation = getHttpOperationWithCache(context, operation);
836
- const sourceOperation =
837
- operation.sourceOperation &&
838
- !isTemplateDeclarationOrInstance(operation.sourceOperation)
839
- ? operation.sourceOperation
840
- : operation;
841
- const sourceOperationGroupName = getOperationGroupName(
842
- context,
843
- sourceOperation
844
- );
845
- const sourceOperationName = getOperationName(context, sourceOperation);
846
- const sourceRoutePath = getHttpOperationWithCache(context, operation).path;
847
- const rlcResponses = rlcModels.responses?.filter((op) => {
848
- return (
849
- (sourceOperationGroupName === "" ||
850
- op.operationGroup === sourceOperationGroupName) &&
851
- op.operationName === sourceOperationName &&
852
- op.path === sourceRoutePath
853
- );
854
- });
855
-
856
- const namespaceHierarchies =
857
- context.rlcOptions?.hierarchyClient === true ? hierarchies : [];
858
-
859
- if (
860
- namespaceHierarchies.length === 0 &&
861
- context.rlcOptions?.hierarchyClient === false &&
862
- operationGroupName !== ""
863
- ) {
864
- namespaceHierarchies.push(operationGroupName);
865
- }
866
-
867
- for (const param of httpOperation.parameters.parameters) {
868
- if (isIgnoredHeaderParam(param)) {
869
- continue;
870
- }
871
- const emittedParam = emitParameter(context, param, "Method");
872
- if (emittedParam === undefined) {
873
- continue;
874
- }
875
- if (isApiVersion(context, param)) {
876
- emittedParam.isApiVersion = true;
877
- methodApiVersionParam = emittedParam;
878
- }
879
- parameters.push(emittedParam);
880
- }
881
-
882
- // Set up responses for operation
883
- const responses: Response[] = [];
884
- const exceptions: Response[] = [];
885
- const isOverload = isSharedRoute(context.program, operation);
886
- for (const response of httpOperation.responses) {
887
- for (const innerResponse of response.responses) {
888
- const emittedResponse: Response = emitResponse(
889
- context,
890
- operation,
891
- response,
892
- innerResponse
893
- );
894
- if (isErrorModel(context.program, response.type)) {
895
- // * is valid status code in typespec but invalid for autorest.python
896
- if (response.statusCode === "*") {
897
- exceptions.push(emittedResponse);
898
- }
899
- } else {
900
- responses.push(emittedResponse);
901
- }
902
- }
903
- }
904
-
905
- let bodyParameter: any | undefined;
906
- if (
907
- httpOperation.parameters.body === undefined ||
908
- isVoidType(httpOperation.parameters.body.type)
909
- ) {
910
- bodyParameter = undefined;
911
- } else {
912
- bodyParameter = emitBodyParameter(context, httpOperation);
913
- // Flatten the body parameter if it is an anonymous model
914
- const originalBodyType = httpOperation.parameters.body.type;
915
-
916
- if (
917
- bodyParameter.type.type === "model" &&
918
- originalBodyType.kind === "Model" &&
919
- originalBodyType.name === "" &&
920
- [...originalBodyType.properties.keys()].every(
921
- (k) =>
922
- operation.parameters.properties.has(k) &&
923
- (operation.parameters.properties.get(k) ===
924
- (originalBodyType as Model).properties.get(k) ||
925
- operation.parameters.properties.get(k) ===
926
- (originalBodyType as Model).properties.get(k)?.sourceProperty)
927
- )
928
- ) {
929
- for (const param of bodyParameter.type.properties) {
930
- param.implementation = "Method";
931
- param.location = param.location ?? "body";
932
- parameters.push(param);
933
- }
934
- bodyParameter = undefined;
935
- } else if (
936
- bodyParameter.type.type === "model" &&
937
- bodyParameter.type.base === "json"
938
- ) {
939
- bodyParameter["propertyToParameterName"] = {};
940
- if (!isOverload) {
941
- bodyParameter.defaultToUnsetSentinel = true;
942
- }
943
- for (const property of bodyParameter.type.properties) {
944
- bodyParameter["propertyToParameterName"][property["restApiName"]] =
945
- property["clientName"];
946
- parameters.push(emitFlattenedParameter(bodyParameter, property));
947
- }
948
- }
949
- }
950
-
951
- const name = applyCasing(getLibraryName(context, operation), {
952
- casing: CASING
953
- });
954
-
955
- /** handle name collision between operation name and parameter signature */
956
- if (bodyParameter) {
957
- bodyParameter.clientName =
958
- bodyParameter.clientName === name
959
- ? bodyParameter.clientName + "Parameter"
960
- : bodyParameter.clientName;
961
- }
962
- parameters
963
- .filter((param) => {
964
- return param.clientName === name && !param.isReadOnly && param.required;
965
- })
966
- .forEach((param) => {
967
- param.clientName = param.clientName + "Parameter";
968
- });
969
- return {
970
- name,
971
- description: getDocStr(context.program, operation),
972
- summary: getSummary(context.program, operation) ?? "",
973
- url: httpOperation.path,
974
- method: httpOperation.verb.toUpperCase(),
975
- parameters: parameters,
976
- bodyParameter: bodyParameter,
977
- responses: responses ?? [],
978
- exceptions: exceptions ?? [],
979
- groupName: operationGroupName,
980
- addedOn: getAddedOnVersion(context.program, operation),
981
- discriminator: "basic",
982
- isOverload,
983
- overloads: [],
984
- apiVersions: [getAddedOnVersion(context.program, operation)],
985
- rlcResponse: rlcResponses?.[0],
986
- namespaceHierarchies
987
- };
988
- }
989
-
990
- function isReadOnly(program: Program, type: ModelProperty): boolean {
991
- // https://microsoft.github.io/typespec/standard-library/http/operations#automatic-visibility
992
- // Only "read" should be readOnly
993
- const visibility = getVisibility(program, type);
994
- if (visibility) {
995
- return visibility.includes("read") && visibility.length === 1;
996
- } else {
997
- return false;
998
- }
999
- }
1000
-
1001
- function emitProperty(
1002
- context: SdkContext,
1003
- property: ModelProperty,
1004
- usage: UsageFlags
1005
- ): Record<string, any> {
1006
- const newProperty = applyEncoding(context.program, property, property);
1007
- let clientDefaultValue = undefined;
1008
- const propertyDefaultKind = property.default?.kind;
1009
- if (
1010
- property.default &&
1011
- (propertyDefaultKind === "Number" ||
1012
- propertyDefaultKind === "String" ||
1013
- propertyDefaultKind === "Boolean")
1014
- ) {
1015
- clientDefaultValue = property.default.value;
1016
- }
1017
-
1018
- if (propertyDefaultKind === "EnumMember") {
1019
- clientDefaultValue = property.default.value ?? property.default.name;
1020
- }
1021
-
1022
- // const [clientName, jsonName] = getPropertyNames(context, property);
1023
- const clientName = getLibraryName(context, property);
1024
- const jsonName = getWireName(context, property);
1025
-
1026
- if (property.model) {
1027
- getType(context, property.model, { usage });
1028
- }
1029
- const type = getType(context, property.type, { usage });
1030
- return {
1031
- clientName: context.rlcOptions?.ignorePropertyNameNormalize
1032
- ? clientName
1033
- : normalizeName(clientName, NameType.Property),
1034
- restApiName: jsonName,
1035
- type: newProperty.format ? { ...type, format: newProperty.format } : type,
1036
- optional: property.optional,
1037
- description: getDocStr(context.program, property),
1038
- addedOn: getAddedOnVersion(context.program, property),
1039
- readonly: isReadOnly(context.program, property),
1040
- clientDefaultValue: clientDefaultValue,
1041
- format: newProperty.format
1042
- };
1043
- }
1044
-
1045
- function getName(program: Program, type: Model): string {
1046
- const friendlyName = getFriendlyName(program, type);
1047
- if (friendlyName) {
1048
- return friendlyName;
1049
- } else {
1050
- if (
1051
- type.templateMapper &&
1052
- type.templateMapper.args &&
1053
- type.name !== "" &&
1054
- type.templateMapper.args.length > 0
1055
- ) {
1056
- return (
1057
- type.name +
1058
- (type.templateMapper.args.filter((it) => isType(it)) as Type[])
1059
- .map((it) => (it.kind === "Model" ? it.name : ""))
1060
- .join("")
1061
- );
1062
- } else {
1063
- return type.name;
1064
- }
1065
- }
1066
- }
1067
-
1068
- export function emitModel(
1069
- context: SdkContext,
1070
- type: Model,
1071
- options: EmitTypeOptions = {}
1072
- ): Record<string, any> {
1073
- // Now we know it's a defined model
1074
- const properties: Record<string, any>[] = [];
1075
- let baseModel = undefined;
1076
- if (type.baseModel) {
1077
- baseModel = getType(context, type.baseModel, options);
1078
- }
1079
- const effectiveName = !options.disableEffectiveModel
1080
- ? getEffectiveSchemaType(context.program, type).name
1081
- : undefined;
1082
- const overridedModelName = normalizeName(
1083
- getLibraryName(context, type) ?? getFriendlyName(context.program, type),
1084
- NameType.Interface,
1085
- true
1086
- );
1087
- const fullNamespaceName =
1088
- getModelNamespaceName(context, type.namespace!)
1089
- .map((nsName) => {
1090
- return normalizeName(nsName, NameType.Interface);
1091
- })
1092
- .join("") +
1093
- (effectiveName ? effectiveName : getName(context.program, type));
1094
- let modelName =
1095
- overridedModelName !== type.name
1096
- ? overridedModelName
1097
- : context.rlcOptions?.enableModelNamespace
1098
- ? fullNamespaceName
1099
- : effectiveName
1100
- ? effectiveName
1101
- : getName(context.program, type);
1102
- if (
1103
- !overridedModelName &&
1104
- type.templateMapper &&
1105
- type.templateMapper.args &&
1106
- type.templateMapper.args.length > 0 &&
1107
- getPagedResult(context.program, type)
1108
- ) {
1109
- modelName =
1110
- (type.templateMapper.args.filter((it) => isType(it)) as Type[])
1111
- .map((it) => {
1112
- switch (it.kind) {
1113
- case "Model":
1114
- return it.name;
1115
- case "String":
1116
- return it.value;
1117
- default:
1118
- return "";
1119
- }
1120
- })
1121
- .join("") + "List";
1122
- }
1123
-
1124
- const page = extractPagedMetadataNested(context.program, type);
1125
- const isPaging = page && page.itemsSegments && page.itemsSegments.length > 0;
1126
- return {
1127
- type: "model",
1128
- name: `${isPaging ? "_" : ""}${modelName}`,
1129
- description: getDocStr(context.program, type),
1130
- parents: baseModel ? [baseModel] : [],
1131
- discriminatedSubtypes: [],
1132
- properties: properties,
1133
- addedOn: getAddedOnVersion(context.program, type),
1134
- snakeCaseName: modelName
1135
- ? applyCasing(modelName, { casing: CASING })
1136
- : modelName,
1137
- base: modelName === "" ? "json" : "dpg",
1138
- coreTypeInfo: buildCoreTypeInfo(context.program, type),
1139
- usage: options.usage
1140
- };
1141
- }
1142
-
1143
- function intOrFloat(value: number): string {
1144
- return value.toString().indexOf(".") === -1 ? "integer" : "float";
1145
- }
1146
-
1147
- function enumName(name: string): string {
1148
- return name;
1149
- }
1150
-
1151
- function emitEnum(context: SdkContext, type: Enum): Record<string, any> {
1152
- const program = context.program;
1153
- const enumValues = [];
1154
- for (const m of type.members.values()) {
1155
- enumValues.push({
1156
- name: enumName(m.name),
1157
- value: m.value ?? m.name,
1158
- description: getDocStr(program, m)
1159
- });
1160
- }
1161
-
1162
- if (enumValues.length === 0) {
1163
- throw new Error(`Expecting enum values but got none`);
1164
- }
1165
- const name = normalizeName(
1166
- getLibraryName(context, type) ? getLibraryName(context, type) : type.name,
1167
- NameType.Interface
1168
- );
1169
- return {
1170
- type: "enum",
1171
- name,
1172
- description:
1173
- getDocStr(program, type) === ""
1174
- ? `Type of ${name}`
1175
- : getDocStr(program, type),
1176
- valueType: { type: enumMemberType(type.members.values().next().value!) },
1177
- values: enumValues,
1178
- isFixed: true,
1179
- coreTypeInfo: buildCoreTypeInfo(program, type)
1180
- };
1181
- }
1182
-
1183
- function enumMemberType(member: EnumMember) {
1184
- if (typeof member.value === "number") {
1185
- return "number";
1186
- }
1187
- return "string";
1188
- }
1189
-
1190
- function constantType(value: any, valueType: string): Record<string, any> {
1191
- return { type: "constant", value: value, valueType: { type: valueType } };
1192
- }
1193
-
1194
- function emitCredential(auth: HttpAuth): Record<string, any> {
1195
- let credential_type: any = {};
1196
- if (auth.type === "oauth2") {
1197
- credential_type = {
1198
- type: "OAuth2",
1199
- policy: {
1200
- type: "BearerTokenCredentialPolicy",
1201
- credentialScopes: []
1202
- }
1203
- };
1204
- for (const flow of auth.flows) {
1205
- for (const scope of flow.scopes) {
1206
- credential_type.policy.credentialScopes.push(scope.value);
1207
- }
1208
- credential_type.policy.credentialScopes.push();
1209
- }
1210
- } else if (auth.type === "apiKey") {
1211
- credential_type = {
1212
- type: "Key",
1213
- policy: {
1214
- type: "AzureKeyCredentialPolicy",
1215
- key: auth.name
1216
- }
1217
- };
1218
- } else if (auth.type === "http") {
1219
- credential_type = {
1220
- type: "Key",
1221
- policy: {
1222
- type: "AzureKeyCredentialPolicy",
1223
- key: "Authorization"
1224
- }
1225
- };
1226
- }
1227
- return credential_type;
1228
- }
1229
-
1230
- function emitCredentialUnion(cred_types: CredentialTypeUnion) {
1231
- const result: any = {};
1232
- // Export as CombinedType, which is already a Union Type in autorest codegen
1233
- result.type = "combined";
1234
- result.types = [];
1235
- for (const cred_type of cred_types.types) {
1236
- result.types.push(emitCredential(cred_type.scheme));
1237
- }
1238
-
1239
- return result;
1240
- }
1241
-
1242
- function emitStdScalar(
1243
- program: Program,
1244
- scalar: Scalar & { name: IntrinsicScalarName }
1245
- ): Record<string, any> {
1246
- const newScalar = applyEncoding(program, scalar, scalar);
1247
- switch (scalar.name) {
1248
- case "bytes":
1249
- return { type: "byte-array", format: newScalar.format };
1250
- case "int8":
1251
- case "int16":
1252
- case "int32":
1253
- case "int64":
1254
- case "safeint":
1255
- case "uint8":
1256
- case "uint16":
1257
- case "uint32":
1258
- case "uint64":
1259
- case "integer":
1260
- return { type: "integer" };
1261
- case "float32":
1262
- case "float64":
1263
- case "float":
1264
- return { type: "float" };
1265
- case "url":
1266
- case "string":
1267
- return { type: "string" };
1268
- case "boolean":
1269
- return { type: "boolean" };
1270
- case "plainDate":
1271
- return { type: "string", format: newScalar.format ?? "date" };
1272
- case "utcDateTime":
1273
- return { type: "datetime", format: newScalar.format };
1274
- case "plainTime":
1275
- return { type: "string", format: newScalar.format ?? "time" };
1276
- case "offsetDateTime":
1277
- return { type: "string" };
1278
- case "duration":
1279
- return { type: "duration", format: newScalar.format };
1280
- case "numeric":
1281
- return {}; // Waiting on design for more precise type https://github.com/microsoft/cadl/issues/1260
1282
- case "decimal":
1283
- case "decimal128":
1284
- reportDiagnostic(program, {
1285
- code: "decimal-to-number",
1286
- format: {
1287
- propertyName: newScalar?.name ?? ""
1288
- },
1289
- target: NoTarget
1290
- });
1291
- return { type: "integer", format: newScalar.format };
1292
- default:
1293
- return {};
1294
- }
1295
- }
1296
-
1297
- function applyEncoding(
1298
- program: Program,
1299
- typespecType: Scalar | ModelProperty,
1300
- target: any = {}
1301
- ) {
1302
- const encodeData = getEncode(program, typespecType);
1303
- if (encodeData) {
1304
- const newTarget = { ...target };
1305
- const newType = emitScalar(program, encodeData.type);
1306
- // newTarget["type"] = newType["type"];
1307
- // If the target already has a format it takes priority. (e.g. int32)
1308
- newTarget["format"] = mergeFormatAndEncoding(
1309
- newTarget.format,
1310
- encodeData.encoding,
1311
- newType["format"]
1312
- );
1313
- return newTarget;
1314
- }
1315
- return target;
1316
- }
1317
-
1318
- function mergeFormatAndEncoding(
1319
- format: string | undefined,
1320
- encoding: string | undefined,
1321
- encodeAsFormat: string | undefined
1322
- ): string | undefined {
1323
- switch (format) {
1324
- case undefined:
1325
- return encodeAsFormat ?? encoding ?? format;
1326
- case "date-time":
1327
- return encoding;
1328
- case "duration":
1329
- default:
1330
- return encodeAsFormat ?? encoding ?? format;
1331
- }
1332
- }
1333
-
1334
- function applyIntrinsicDecorators(
1335
- program: Program,
1336
- type: Scalar | ModelProperty,
1337
- result: any
1338
- ): Record<string, any> {
1339
- let newResult = { ...result };
1340
- const docStr = getDoc(program, type);
1341
- const isString = isStringType(program, getPropertyType(type));
1342
- const isNumeric = isNumericType(program, getPropertyType(type));
1343
-
1344
- if (!result.description && docStr) {
1345
- newResult.description = docStr;
1346
- }
1347
-
1348
- newResult = applyEncoding(program, type, newResult);
1349
-
1350
- const pattern = getPattern(program, type);
1351
- if (isString && !result.pattern && pattern) {
1352
- newResult.pattern = pattern;
1353
- }
1354
-
1355
- const minLength = getMinLength(program, type);
1356
- if (isString && !result.minLength && minLength !== undefined) {
1357
- newResult.minLength = minLength;
1358
- }
1359
-
1360
- const maxLength = getMaxLength(program, type);
1361
- if (isString && !result.maxLength && maxLength !== undefined) {
1362
- newResult.maxLength = maxLength;
1363
- }
1364
-
1365
- const minValue = getMinValue(program, type);
1366
- if (isNumeric && !result.minimum && minValue !== undefined) {
1367
- newResult.minimum = minValue;
1368
- }
1369
-
1370
- const maxValue = getMaxValue(program, type);
1371
- if (isNumeric && !result.maximum && maxValue !== undefined) {
1372
- newResult.maximum = maxValue;
1373
- }
1374
-
1375
- const minItems = getMinItems(program, type);
1376
- if (!result.minItems && minItems !== undefined) {
1377
- newResult.minItems = minItems;
1378
- }
1379
-
1380
- const maxItems = getMaxItems(program, type);
1381
- if (!result.maxItems && maxItems !== undefined) {
1382
- newResult.maxItems = maxItems;
1383
- }
1384
- return newResult;
1385
- }
1386
-
1387
- function emitScalar(program: Program, scalar: Scalar): Record<string, any> {
1388
- let result: Record<string, any> = {};
1389
- const isStd = program.checker.isStdType(scalar);
1390
- if (isStd) {
1391
- result = emitStdScalar(program, scalar);
1392
- } else if (scalar.baseScalar) {
1393
- result = emitScalar(program, scalar.baseScalar);
1394
- }
1395
- return applyIntrinsicDecorators(program, scalar, result);
1396
- }
1397
-
1398
- function emitListOrDict(
1399
- context: SdkContext,
1400
- type: Model,
1401
- usage: UsageFlags
1402
- ): Record<string, any> | undefined {
1403
- if (type.indexer !== undefined) {
1404
- if (!isNeverType(type.indexer.key)) {
1405
- const name = type.indexer.key.name;
1406
- if (name === "string") {
1407
- return {
1408
- type: "dict",
1409
- name: type.name,
1410
- elementType: getType(context, type.indexer.value!, { usage })
1411
- };
1412
- } else if (name === "integer") {
1413
- return {
1414
- type: "list",
1415
- elementType: getType(context, type.indexer.value!, { usage })
1416
- };
1417
- }
1418
- }
1419
- }
1420
- return undefined;
1421
- }
1422
-
1423
- function mapTypeSpecType(
1424
- context: SdkContext,
1425
- type: Type,
1426
- usage: UsageFlags
1427
- ): any {
1428
- switch (type.kind) {
1429
- case "Number":
1430
- return constantType(type.value, intOrFloat(type.value));
1431
- case "String":
1432
- return constantType(type.value, "string");
1433
- case "Boolean":
1434
- return constantType(type.value, "boolean");
1435
- case "Model":
1436
- return emitListOrDict(context, type, usage);
1437
- }
1438
- }
1439
-
1440
- function emitUnion(
1441
- context: SdkContext,
1442
- type: Union,
1443
- usage: UsageFlags
1444
- ): Record<string, any> {
1445
- let sdkType = getSdkUnion(context, type);
1446
- const isNull = sdkType.kind === "nullable";
1447
- if (sdkType.kind === "nullable") {
1448
- sdkType = sdkType.type;
1449
- }
1450
- const nonNullOptions = getNonNullOptions(type);
1451
- if (sdkType === undefined) {
1452
- throw Error("Should not have an empty union");
1453
- }
1454
- if (sdkType.kind === "union") {
1455
- const unionName = getLibraryName(context, type)
1456
- ? getLibraryName(context, type)
1457
- : type.name;
1458
- const discriminatorPropertyName = getDiscriminator(
1459
- context.program,
1460
- type
1461
- )?.propertyName;
1462
- const variantTypes = sdkType.variantTypes.map((x) => {
1463
- const valueType = getType(context, x.__raw!, { usage });
1464
- if (valueType.properties && discriminatorPropertyName) {
1465
- valueType.discriminatorValue = valueType.properties.filter(
1466
- (p: Property) => p.clientName === discriminatorPropertyName
1467
- )[0].type.value;
1468
- }
1469
- return valueType;
1470
- });
1471
- const unionTypeName = unionName
1472
- ? normalizeName(unionName, NameType.Interface)
1473
- : undefined;
1474
- return {
1475
- nullable: isNull,
1476
- name: unionTypeName,
1477
- description: `Type of ${unionTypeName}`,
1478
- internal: true,
1479
- type: "combined",
1480
- types: variantTypes,
1481
- xmlMetadata: {},
1482
- usage,
1483
- discriminator: discriminatorPropertyName,
1484
- alias:
1485
- unionName === "" || unionName === undefined ? undefined : unionName,
1486
- aliasType:
1487
- unionName === "" || unionName === undefined
1488
- ? undefined
1489
- : variantTypes.map((x) => getTypeName(x).name).join(" | "),
1490
- tcgcType: sdkType
1491
- };
1492
- } else if (sdkType.kind === "enum") {
1493
- let typeName = getLibraryName(context, type)
1494
- ? getLibraryName(context, type)
1495
- : sdkType.isGeneratedName
1496
- ? type.name
1497
- : sdkType.name;
1498
- typeName = typeName
1499
- ? normalizeName(typeName, NameType.Interface)
1500
- : undefined;
1501
- return {
1502
- name: typeName,
1503
- nullable: isNull,
1504
- description: sdkType.doc || `Type of ${typeName}`,
1505
- internal: true,
1506
- type: sdkType.kind,
1507
- valueType: emitSimpleType(sdkType.valueType),
1508
- values: sdkType.values.map((x) => emitEnumMember(context, x)),
1509
- isFixed: sdkType.isFixed,
1510
- isNonExhaustive: context.rlcOptions?.experimentalExtensibleEnums ?? false,
1511
- xmlMetadata: {},
1512
- usage
1513
- };
1514
- } else if (nonNullOptions.length === 1 && nonNullOptions[0]) {
1515
- return {
1516
- ...emitType(context, nonNullOptions[0], { usage }),
1517
- nullable: isNull
1518
- };
1519
- } else {
1520
- return {
1521
- ...emitType(context, sdkType.__raw!, { usage }),
1522
- nullable: isNull
1523
- };
1524
- }
1525
- }
1526
-
1527
- function getNonNullOptions(type: Union) {
1528
- return [...type.variants.values()]
1529
- .map((x) => x.type)
1530
- .filter((t) => !isNullType(t));
1531
- }
1532
-
1533
- function emitEnumMember(context: SdkContext, member: any): Record<string, any> {
1534
- const value = member.value ?? member.name;
1535
- return {
1536
- type: "constant",
1537
- valueType: {
1538
- type: enumMemberType(member)
1539
- },
1540
- value,
1541
- name: member.name ? enumName(member.name) : undefined,
1542
- description: getDoc(context.program, member),
1543
- isConstant: true
1544
- };
1545
- }
1546
-
1547
- function emitSimpleType(type: SdkBuiltInType): Record<string, any> {
1548
- return {
1549
- nullable: isNullType(type.__raw!),
1550
- type: type.kind === "string" ? "string" : "number", // TODO: handle other types
1551
- doc: "",
1552
- apiVersions: [],
1553
- sdkDefaultValue: undefined,
1554
- format: undefined
1555
- };
1556
- }
1557
-
1558
- function emitType(
1559
- context: SdkContext,
1560
- type: EmitterType,
1561
- options: EmitTypeOptions = {}
1562
- ): Record<string, any> {
1563
- if (type.kind === "Credential") {
1564
- return emitCredential(type.scheme);
1565
- }
1566
- if (type.kind === "CredentialTypeUnion") {
1567
- return emitCredentialUnion(type);
1568
- }
1569
- const builtinType = mapTypeSpecType(context, type, options.usage!);
1570
- if (builtinType !== undefined) {
1571
- // add in description elements for types derived from primitive types (SecureString, etc.)
1572
- const doc = getDoc(context.program, type);
1573
- if (doc) {
1574
- builtinType.description = doc;
1575
- }
1576
- return builtinType;
1577
- }
1578
-
1579
- switch (type.kind) {
1580
- case "Intrinsic":
1581
- return { type: type.name };
1582
- case "Model":
1583
- return emitModel(context, type, options);
1584
- case "Scalar":
1585
- return emitScalar(context.program, type);
1586
- case "Union":
1587
- return emitUnion(context, type, options.usage!);
1588
- case "UnionVariant":
1589
- return emitType(context, type.type, options);
1590
- case "Enum":
1591
- return emitEnum(context, type);
1592
- case "EnumMember":
1593
- return emitEnumMember(context, type);
1594
- case "ModelProperty":
1595
- return emitType(context, type.type, options);
1596
- default:
1597
- throw Error(`Not supported ${type.kind}`);
1598
- }
1599
- }
1600
-
1601
- function emitOperationGroups(
1602
- context: SdkContext,
1603
- client: SdkClient,
1604
- rlcModels: RLCModel
1605
- ): OperationGroup[] {
1606
- const operationGroups: OperationGroup[] = [];
1607
- const groupMapping: Map<string, OperationGroup> = new Map<
1608
- string,
1609
- OperationGroup
1610
- >();
1611
- const clientOperations: HrlcOperation[] = [];
1612
- for (const operation of listOperationsInOperationGroup(context, client)) {
1613
- clientOperations.push(emitOperation(context, operation, "", rlcModels, []));
1614
- }
1615
- if (clientOperations.length > 0) {
1616
- addHierarchyOperationGroup(clientOperations, groupMapping);
1617
- }
1618
- for (const operationGroup of listOperationGroups(context, client, true)) {
1619
- const operations: HrlcOperation[] = [];
1620
- const overrideName = getLibraryName(context, operationGroup.type);
1621
- const name =
1622
- context.rlcOptions?.hierarchyClient ||
1623
- context.rlcOptions?.enableOperationGroup
1624
- ? (overrideName ?? operationGroup.type.name)
1625
- : "";
1626
- const hierarchies =
1627
- context.rlcOptions?.hierarchyClient ||
1628
- context.rlcOptions?.enableOperationGroup
1629
- ? operationGroup.groupPath.split(".")
1630
- : [];
1631
- if (hierarchies[0]?.endsWith("Client")) {
1632
- hierarchies.shift();
1633
- }
1634
- for (const operation of listOperationsInOperationGroup(
1635
- context,
1636
- operationGroup
1637
- )) {
1638
- operations.push(
1639
- emitOperation(context, operation, name, rlcModels, hierarchies)
1640
- );
1641
- }
1642
- if (operations.length > 0) {
1643
- addHierarchyOperationGroup(operations, groupMapping);
1644
- }
1645
- }
1646
-
1647
- groupMapping.forEach((value) => {
1648
- operationGroups.push(value);
1649
- });
1650
- if (
1651
- context.rlcOptions?.hierarchyClient === false &&
1652
- context.rlcOptions?.enableOperationGroup
1653
- ) {
1654
- appendOperationGroupPrefix(operationGroups);
1655
- }
1656
- return operationGroups;
1657
- }
1658
-
1659
- function addHierarchyOperationGroup(
1660
- operations: HrlcOperation[],
1661
- groupMapping: Map<string, OperationGroup>
1662
- ): OperationGroup[] {
1663
- if (operations.length > 0) {
1664
- operations.forEach((op) => {
1665
- const groupName = op.namespaceHierarchies.join("") ?? "";
1666
- if (!groupMapping.has(groupName)) {
1667
- groupMapping.set(groupName, {
1668
- className: groupName,
1669
- propertyName: groupName,
1670
- operations: [op],
1671
- namespaceHierarchies: op.namespaceHierarchies
1672
- });
1673
- } else {
1674
- groupMapping.get(groupName)!.operations.push(op);
1675
- }
1676
- });
1677
- return [...groupMapping.values()];
1678
- }
1679
- return [];
1680
- }
1681
-
1682
- function appendOperationGroupPrefix(operationGroups: OperationGroup[]) {
1683
- if (operationGroups.length < 2) {
1684
- return;
1685
- }
1686
- // Append operation group prefix
1687
- operationGroups.forEach((g) =>
1688
- g.operations.forEach((op) => {
1689
- op.oriName = op.name;
1690
- op.name = `${g.propertyName}_${op.name}`;
1691
- })
1692
- );
1693
- }
1694
-
1695
- function getServerHelper(
1696
- program: Program,
1697
- namespace: Namespace
1698
- ): HttpServer | undefined {
1699
- const servers = getServers(program, namespace);
1700
- if (servers === undefined) {
1701
- return undefined;
1702
- }
1703
- return servers[0];
1704
- }
1705
-
1706
- function emitServerParams(
1707
- context: SdkContext,
1708
- namespace: Namespace
1709
- ): Parameter[] {
1710
- const server = getServerHelper(context.program, namespace);
1711
- if (server === undefined || server.parameters.size === 0) {
1712
- return [
1713
- {
1714
- optional: false,
1715
- description: "Service host",
1716
- clientName: "endpointParam",
1717
- clientDefaultValue: null,
1718
- restApiName: "endpoint",
1719
- location: "endpointPath",
1720
- type: { type: "string" },
1721
- implementation: "Client",
1722
- inOverload: false
1723
- }
1724
- ];
1725
- }
1726
- if (server.parameters) {
1727
- const params: Parameter[] = [];
1728
- for (const param of server.parameters.values()) {
1729
- const serverParameter: HttpServerParameter = {
1730
- type: "endpointPath",
1731
- name: param.name,
1732
- param: param
1733
- };
1734
- const emittedParameter = emitParameter(
1735
- context,
1736
- serverParameter,
1737
- "Client"
1738
- );
1739
- if (emittedParameter === undefined) {
1740
- continue;
1741
- }
1742
- endpointPathParameters.push(emittedParameter);
1743
- if (isApiVersion(context, serverParameter as any)) {
1744
- emittedParameter.isApiVersion = true;
1745
- serverApiVersionParam = emittedParameter;
1746
- emittedParameter.isApiVersion = true;
1747
- }
1748
- params.push(emittedParameter);
1749
- }
1750
- return params;
1751
- } else {
1752
- return [
1753
- {
1754
- optional: false,
1755
- description: "Service host",
1756
- clientName: "endpointParam",
1757
- clientDefaultValue: server.url,
1758
- restApiName: "endpoint",
1759
- location: "path",
1760
- type: { type: "string" },
1761
- implementation: "Client",
1762
- inOverload: false
1763
- }
1764
- ];
1765
- }
1766
- }
1767
-
1768
- function emitCredentialParam(
1769
- context: SdkContext,
1770
- namespace: Namespace
1771
- ): Parameter | undefined {
1772
- const auth = getAuthentication(context.program, namespace);
1773
- if (auth) {
1774
- const credential_types: CredentialType[] = [];
1775
- for (const scheme of getSupportedHttpAuth(context.program, auth)) {
1776
- const type: CredentialType = {
1777
- kind: "Credential",
1778
- scheme: scheme
1779
- };
1780
- credential_types.push(type);
1781
- }
1782
-
1783
- if (
1784
- credential_types.length > 0 &&
1785
- context.rlcOptions?.addCredentials !== false
1786
- ) {
1787
- let type: EmitterType;
1788
- if (credential_types.length === 1 && credential_types[0]) {
1789
- type = credential_types[0];
1790
- } else {
1791
- type = {
1792
- kind: "CredentialTypeUnion",
1793
- types: credential_types
1794
- };
1795
- }
1796
- return {
1797
- type: getType(context, type, { usage: UsageFlags.Input }),
1798
- optional: false,
1799
- description: "Credential needed for the client to connect to Azure.",
1800
- clientName: "credential",
1801
- location: "other",
1802
- restApiName: "credential",
1803
- implementation: "Client",
1804
- skipUrlEncoding: true,
1805
- inOverload: false
1806
- };
1807
- }
1808
- }
1809
- return undefined;
1810
- }
1811
-
1812
- function emitGlobalParameters(
1813
- context: SdkContext,
1814
- namespace: Namespace
1815
- ): Parameter[] {
1816
- const clientParameters = emitServerParams(context, namespace);
1817
- const credentialParam = emitCredentialParam(context, namespace);
1818
- if (credentialParam) {
1819
- clientParameters.push(credentialParam);
1820
- }
1821
- return clientParameters;
1822
- }
1823
-
1824
- function getMethodApiVersionParameter(): Parameter | void {
1825
- if (methodApiVersionParam) {
1826
- return {
1827
- ...methodApiVersionParam,
1828
- isApiVersion: true
1829
- };
1830
- }
1831
- }
1832
-
1833
- function emitClients(
1834
- context: SdkContext,
1835
- rlcModelsMap: Map<string, RLCModel>
1836
- ): HrlcClient[] {
1837
- const program = context.program;
1838
- const clients = listClients(context);
1839
- const retval: HrlcClient[] = [];
1840
- methodApiVersionParam = undefined;
1841
- for (const client of clients) {
1842
- const sdkPackageClient = context.sdkPackage.clients.find((p) => {
1843
- return p.name === client.name;
1844
- });
1845
-
1846
- if (!sdkPackageClient) {
1847
- throw new Error(`Client ${client.name} not found in the SDK package`);
1848
- }
1849
-
1850
- const clientName = client.name.replace("Client", "");
1851
- const server = getServerHelper(program, client.service);
1852
- const rlcModels = rlcModelsMap.get(client.service.name);
1853
- if (!rlcModels) {
1854
- continue;
1855
- }
1856
- const emittedClient: HrlcClient = {
1857
- name: clientName.split(".").at(-1) ?? "",
1858
- description: getDocStr(program, client.type),
1859
- parameters: emitGlobalParameters(context, client.service),
1860
- operationGroups: emitOperationGroups(context, client, rlcModels),
1861
- tcgcClient: sdkPackageClient,
1862
- url: server ? server.url : "",
1863
- apiVersions: [],
1864
- rlcClientName: `${client.name.replace("Client", "")}Context`,
1865
- subfolder: "",
1866
- rlcHelperDetails:
1867
- rlcModels && rlcModels.helperDetails ? rlcModels.helperDetails : {}
1868
- };
1869
- const methodApiVersionParam = getMethodApiVersionParameter();
1870
- if (
1871
- methodApiVersionParam &&
1872
- !serverApiVersionParam &&
1873
- context.hasApiVersionInClient
1874
- ) {
1875
- // prompt method-level api version to client level only when there is no client one defined
1876
- emittedClient.parameters.push(methodApiVersionParam);
1877
- // if we have client level api version, we need to remove it from all operations
1878
- emittedClient.operationGroups.map((opGroup) => {
1879
- opGroup.operations.map((op) => {
1880
- op.parameters = op.parameters.filter((param) => {
1881
- return !param.isApiVersion;
1882
- });
1883
- return op;
1884
- });
1885
- return opGroup;
1886
- });
1887
- }
1888
- retval.push(emittedClient);
1889
- }
1890
- return retval;
1891
- }
1892
-
1893
- function getServiceNamespace(program: Program): Namespace {
1894
- return listServices(program)[0]!.type;
1895
- }
1896
-
1897
- function getNamespace(context: SdkContext, clientName: string): string {
1898
- // We get client namespaces from the client name. If there's a dot, we add that to the namespace
1899
- const submodule = clientName.split(".").slice(0, -1).join(".").toLowerCase();
1900
- if (!submodule) {
1901
- return getClientNamespaceString(context)!.toLowerCase();
1902
- }
1903
- return submodule;
1904
- }
1905
-
1906
- function getNamespaces(context: SdkContext): Set<string> {
1907
- const namespaces = new Set<string>();
1908
- for (const client of listClients(context)) {
1909
- namespaces.add(getNamespace(context, client.name));
1910
- }
1911
- return namespaces;
1912
- }
1913
-
1914
- export function emitCodeModel(
1915
- dpgContext: SdkContext,
1916
- rlcModelsMap: Map<string, RLCModel>,
1917
- modularSourcesRoot: string,
1918
- project: Project,
1919
- options: { casing: "snake" | "camel" } = { casing: "snake" }
1920
- ): ModularCodeModel {
1921
- CASING = options.casing ?? CASING;
1922
- const clientNamespaceString =
1923
- getClientNamespaceString(dpgContext)?.toLowerCase();
1924
- // Get types
1925
- const codeModel: ModularCodeModel = {
1926
- options: dpgContext.rlcOptions ?? {},
1927
- modularOptions: {
1928
- sourceRoot: modularSourcesRoot,
1929
- compatibilityMode: !!dpgContext.rlcOptions?.compatibilityMode,
1930
- experimentalExtensibleEnums:
1931
- !!dpgContext.rlcOptions?.experimentalExtensibleEnums
1932
- },
1933
- namespace: clientNamespaceString,
1934
- clients: [],
1935
- types: [],
1936
- project,
1937
- runtimeImports: buildRuntimeImports(dpgContext.rlcOptions?.flavor)
1938
- };
1939
-
1940
- typesMap.clear();
1941
- simpleTypesMap.clear();
1942
- const allModels = getAllModels(dpgContext);
1943
- for (const model of allModels) {
1944
- getType(dpgContext, model.__raw!, { usage: model.usage as UsageFlags });
1945
- }
1946
- for (const namespace of getNamespaces(dpgContext)) {
1947
- if (namespace === clientNamespaceString) {
1948
- codeModel.clients = emitClients(dpgContext, rlcModelsMap);
1949
- codeModel.clients.length > 1 &&
1950
- codeModel.clients.map((client) => {
1951
- client["subfolder"] = normalizeName(
1952
- client.name.replace("Client", ""),
1953
- NameType.File
1954
- );
1955
- });
1956
- }
1957
- }
1958
-
1959
- codeModel["types"] = [
1960
- { type: "string" },
1961
- ...typesMap.values(),
1962
- ...simpleTypesMap.values()
1963
- ];
1964
- return codeModel;
1965
- }