@azure-tools/typespec-ts 0.33.0 → 0.34.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 (199) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/src/framework/declaration.js.map +1 -1
  3. package/dist/src/framework/dependency.d.ts +25 -0
  4. package/dist/src/framework/dependency.d.ts.map +1 -1
  5. package/dist/src/framework/hooks/binder.d.ts +1 -1
  6. package/dist/src/framework/hooks/binder.d.ts.map +1 -1
  7. package/dist/src/framework/hooks/binder.js +16 -12
  8. package/dist/src/framework/hooks/binder.js.map +1 -1
  9. package/dist/src/framework/hooks/sdkTypes.d.ts +4 -2
  10. package/dist/src/framework/hooks/sdkTypes.d.ts.map +1 -1
  11. package/dist/src/framework/hooks/sdkTypes.js +43 -8
  12. package/dist/src/framework/hooks/sdkTypes.js.map +1 -1
  13. package/dist/src/framework/refkey.js +1 -1
  14. package/dist/src/framework/refkey.js.map +1 -1
  15. package/dist/src/framework/sample.js +1 -1
  16. package/dist/src/framework/sample.js.map +1 -1
  17. package/dist/src/index.d.ts +2 -0
  18. package/dist/src/index.d.ts.map +1 -1
  19. package/dist/src/index.js +81 -24
  20. package/dist/src/index.js.map +1 -1
  21. package/dist/src/lib.d.ts +37 -3
  22. package/dist/src/lib.d.ts.map +1 -1
  23. package/dist/src/lib.js +26 -1
  24. package/dist/src/lib.js.map +1 -1
  25. package/dist/src/modular/buildClassicalClient.d.ts +2 -2
  26. package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
  27. package/dist/src/modular/buildClassicalClient.js +25 -61
  28. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  29. package/dist/src/modular/buildClassicalOperationGroups.d.ts.map +1 -1
  30. package/dist/src/modular/buildClassicalOperationGroups.js +0 -7
  31. package/dist/src/modular/buildClassicalOperationGroups.js.map +1 -1
  32. package/dist/src/modular/buildClientContext.d.ts +7 -3
  33. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  34. package/dist/src/modular/buildClientContext.js +58 -38
  35. package/dist/src/modular/buildClientContext.js.map +1 -1
  36. package/dist/src/modular/buildCodeModel.d.ts +18 -0
  37. package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
  38. package/dist/src/modular/buildCodeModel.js +95 -42
  39. package/dist/src/modular/buildCodeModel.js.map +1 -1
  40. package/dist/src/modular/buildOperations.d.ts +3 -4
  41. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  42. package/dist/src/modular/buildOperations.js +24 -45
  43. package/dist/src/modular/buildOperations.js.map +1 -1
  44. package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
  45. package/dist/src/modular/buildProjectFiles.js +3 -1
  46. package/dist/src/modular/buildProjectFiles.js.map +1 -1
  47. package/dist/src/modular/buildRestorePoller.js +1 -1
  48. package/dist/src/modular/buildRestorePoller.js.map +1 -1
  49. package/dist/src/modular/buildRootIndex.d.ts +5 -0
  50. package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
  51. package/dist/src/modular/buildRootIndex.js +62 -17
  52. package/dist/src/modular/buildRootIndex.js.map +1 -1
  53. package/dist/src/modular/buildSubpathIndex.d.ts +1 -1
  54. package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
  55. package/dist/src/modular/buildSubpathIndex.js +11 -10
  56. package/dist/src/modular/buildSubpathIndex.js.map +1 -1
  57. package/dist/src/modular/emitModels.d.ts +13 -28
  58. package/dist/src/modular/emitModels.d.ts.map +1 -1
  59. package/dist/src/modular/emitModels.js +435 -240
  60. package/dist/src/modular/emitModels.js.map +1 -1
  61. package/dist/src/modular/emitModelsOptions.d.ts +26 -0
  62. package/dist/src/modular/emitModelsOptions.d.ts.map +1 -0
  63. package/dist/src/modular/emitModelsOptions.js +106 -0
  64. package/dist/src/modular/emitModelsOptions.js.map +1 -0
  65. package/dist/src/modular/emitSamples.d.ts +7 -0
  66. package/dist/src/modular/emitSamples.d.ts.map +1 -0
  67. package/dist/src/modular/emitSamples.js +354 -0
  68. package/dist/src/modular/emitSamples.js.map +1 -0
  69. package/dist/src/modular/external-dependencies.d.ts +7 -0
  70. package/dist/src/modular/external-dependencies.d.ts.map +1 -1
  71. package/dist/src/modular/external-dependencies.js +58 -1
  72. package/dist/src/modular/external-dependencies.js.map +1 -1
  73. package/dist/src/modular/helpers/classicalOperationHelpers.d.ts.map +1 -1
  74. package/dist/src/modular/helpers/classicalOperationHelpers.js +2 -2
  75. package/dist/src/modular/helpers/classicalOperationHelpers.js.map +1 -1
  76. package/dist/src/modular/helpers/clientHelpers.d.ts +13 -6
  77. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  78. package/dist/src/modular/helpers/clientHelpers.js +117 -48
  79. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  80. package/dist/src/modular/helpers/namingHelpers.d.ts +3 -2
  81. package/dist/src/modular/helpers/namingHelpers.d.ts.map +1 -1
  82. package/dist/src/modular/helpers/namingHelpers.js +3 -0
  83. package/dist/src/modular/helpers/namingHelpers.js.map +1 -1
  84. package/dist/src/modular/helpers/operationHelpers.d.ts +9 -11
  85. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  86. package/dist/src/modular/helpers/operationHelpers.js +255 -408
  87. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  88. package/dist/src/modular/helpers/typeHelpers.d.ts +12 -0
  89. package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
  90. package/dist/src/modular/helpers/typeHelpers.js +30 -6
  91. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  92. package/dist/src/modular/modularCodeModel.d.ts +2 -1
  93. package/dist/src/modular/modularCodeModel.d.ts.map +1 -1
  94. package/dist/src/modular/serialization/buildDeserializerFunction.d.ts +5 -0
  95. package/dist/src/modular/serialization/buildDeserializerFunction.d.ts.map +1 -0
  96. package/dist/src/modular/serialization/buildDeserializerFunction.js +327 -0
  97. package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -0
  98. package/dist/src/modular/serialization/buildSerializerFunction.d.ts +4 -3
  99. package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -1
  100. package/dist/src/modular/serialization/buildSerializerFunction.js +285 -102
  101. package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
  102. package/dist/src/modular/serialization/serializeUtils.d.ts +15 -0
  103. package/dist/src/modular/serialization/serializeUtils.d.ts.map +1 -0
  104. package/dist/src/modular/serialization/serializeUtils.js +102 -0
  105. package/dist/src/modular/serialization/serializeUtils.js.map +1 -0
  106. package/dist/src/modular/type-expressions/get-credential-expression.d.ts +3 -0
  107. package/dist/src/modular/type-expressions/get-credential-expression.d.ts.map +1 -0
  108. package/dist/src/modular/type-expressions/get-credential-expression.js +17 -0
  109. package/dist/src/modular/type-expressions/get-credential-expression.js.map +1 -0
  110. package/dist/src/modular/type-expressions/get-enum-expression.d.ts +6 -0
  111. package/dist/src/modular/type-expressions/get-enum-expression.d.ts.map +1 -0
  112. package/dist/src/modular/type-expressions/get-enum-expression.js +18 -0
  113. package/dist/src/modular/type-expressions/get-enum-expression.js.map +1 -0
  114. package/dist/src/modular/type-expressions/get-model-expression.d.ts +9 -0
  115. package/dist/src/modular/type-expressions/get-model-expression.d.ts.map +1 -0
  116. package/dist/src/modular/type-expressions/get-model-expression.js +42 -0
  117. package/dist/src/modular/type-expressions/get-model-expression.js.map +1 -0
  118. package/dist/src/modular/type-expressions/get-type-expression.d.ts +8 -0
  119. package/dist/src/modular/type-expressions/get-type-expression.d.ts.map +1 -0
  120. package/dist/src/modular/type-expressions/get-type-expression.js +94 -0
  121. package/dist/src/modular/type-expressions/get-type-expression.js.map +1 -0
  122. package/dist/src/modular/type-expressions/get-union-expression.d.ts +5 -0
  123. package/dist/src/modular/type-expressions/get-union-expression.d.ts.map +1 -0
  124. package/dist/src/modular/type-expressions/get-union-expression.js +13 -0
  125. package/dist/src/modular/type-expressions/get-union-expression.js.map +1 -0
  126. package/dist/src/modular/type-expressions/utils.d.ts +5 -0
  127. package/dist/src/modular/type-expressions/utils.d.ts.map +1 -0
  128. package/dist/src/modular/type-expressions/utils.js +9 -0
  129. package/dist/src/modular/type-expressions/utils.js.map +1 -0
  130. package/dist/src/transform/transform.js +1 -1
  131. package/dist/src/transform/transform.js.map +1 -1
  132. package/dist/src/transform/transformApiVersionInfo.js +1 -1
  133. package/dist/src/transform/transformApiVersionInfo.js.map +1 -1
  134. package/dist/src/transform/transformParameters.js +1 -1
  135. package/dist/src/transform/transformParameters.js.map +1 -1
  136. package/dist/src/transform/transformSchemas.d.ts.map +1 -1
  137. package/dist/src/transform/transformSchemas.js +3 -3
  138. package/dist/src/transform/transformSchemas.js.map +1 -1
  139. package/dist/src/utils/clientUtils.d.ts.map +1 -1
  140. package/dist/src/utils/clientUtils.js +1 -4
  141. package/dist/src/utils/clientUtils.js.map +1 -1
  142. package/dist/src/utils/credentialUtils.d.ts +5 -0
  143. package/dist/src/utils/credentialUtils.d.ts.map +1 -1
  144. package/dist/src/utils/credentialUtils.js +36 -4
  145. package/dist/src/utils/credentialUtils.js.map +1 -1
  146. package/dist/src/utils/modelUtils.d.ts.map +1 -1
  147. package/dist/src/utils/modelUtils.js +28 -43
  148. package/dist/src/utils/modelUtils.js.map +1 -1
  149. package/dist/tsconfig.tsbuildinfo +1 -1
  150. package/package.json +26 -26
  151. package/src/framework/declaration.ts +0 -1
  152. package/src/framework/dependency.ts +25 -0
  153. package/src/framework/hooks/binder.ts +19 -14
  154. package/src/framework/hooks/sdkTypes.ts +53 -13
  155. package/src/framework/refkey.ts +1 -1
  156. package/src/framework/sample.ts +1 -1
  157. package/src/index.ts +96 -25
  158. package/src/lib.ts +26 -3
  159. package/src/modular/buildClassicalClient.ts +30 -97
  160. package/src/modular/buildClassicalOperationGroups.ts +0 -14
  161. package/src/modular/buildClientContext.ts +90 -50
  162. package/src/modular/buildCodeModel.ts +118 -47
  163. package/src/modular/buildOperations.ts +41 -76
  164. package/src/modular/buildProjectFiles.ts +4 -2
  165. package/src/modular/buildRestorePoller.ts +1 -1
  166. package/src/modular/buildRootIndex.ts +75 -35
  167. package/src/modular/buildSubpathIndex.ts +13 -11
  168. package/src/modular/emitModels.ts +588 -326
  169. package/src/modular/emitModelsOptions.ts +161 -0
  170. package/src/modular/emitSamples.ts +481 -0
  171. package/src/modular/external-dependencies.ts +59 -1
  172. package/src/modular/helpers/classicalOperationHelpers.ts +6 -2
  173. package/src/modular/helpers/clientHelpers.ts +182 -76
  174. package/src/modular/helpers/namingHelpers.ts +14 -2
  175. package/src/modular/helpers/operationHelpers.ts +356 -638
  176. package/src/modular/helpers/typeHelpers.ts +38 -6
  177. package/src/modular/modularCodeModel.ts +3 -0
  178. package/src/modular/serialization/buildDeserializerFunction.ts +492 -0
  179. package/src/modular/serialization/buildSerializerFunction.ts +434 -141
  180. package/src/modular/serialization/serializeUtils.ts +143 -0
  181. package/src/modular/type-expressions/get-credential-expression.ts +18 -0
  182. package/src/modular/type-expressions/get-enum-expression.ts +28 -0
  183. package/src/modular/type-expressions/get-model-expression.ts +63 -0
  184. package/src/modular/type-expressions/get-type-expression.ts +111 -0
  185. package/src/modular/type-expressions/get-union-expression.ts +20 -0
  186. package/src/modular/type-expressions/utils.ts +15 -0
  187. package/src/transform/transform.ts +2 -2
  188. package/src/transform/transformApiVersionInfo.ts +2 -2
  189. package/src/transform/transformParameters.ts +1 -1
  190. package/src/transform/transformSchemas.ts +9 -8
  191. package/src/utils/clientUtils.ts +2 -12
  192. package/src/utils/credentialUtils.ts +43 -3
  193. package/src/utils/modelUtils.ts +32 -41
  194. package/static/static-helpers/serialization/serializers.ts +60 -0
  195. package/dist/src/modular/buildSerializeUtils.d.ts +0 -14
  196. package/dist/src/modular/buildSerializeUtils.d.ts.map +0 -1
  197. package/dist/src/modular/buildSerializeUtils.js +0 -534
  198. package/dist/src/modular/buildSerializeUtils.js.map +0 -1
  199. package/src/modular/buildSerializeUtils.ts +0 -749
@@ -1,298 +1,493 @@
1
- import * as path from "path";
2
- import { addImportsToFiles, getImportSpecifier } from "@azure-tools/rlc-common";
1
+ import { StructureKind } from "ts-morph";
2
+ import { NameType, normalizeName } from "@azure-tools/rlc-common";
3
+ import { UsageFlags, isReadOnly } from "@azure-tools/typespec-client-generator-core";
4
+ import { getExternalModel, getModelExpression } from "./type-expressions/get-model-expression.js";
5
+ import { addDeclaration } from "../framework/declaration.js";
3
6
  import { addImportBySymbol } from "../utils/importHelper.js";
7
+ import { buildModelDeserializer } from "./serialization/buildDeserializerFunction.js";
4
8
  import { buildModelSerializer } from "./serialization/buildSerializerFunction.js";
5
- import { buildOperationOptions } from "./buildOperations.js";
6
- import { getDocsFromDescription } from "./helpers/docsHelpers.js";
7
- import { getModularModelFilePath } from "./helpers/namingHelpers.js";
8
- import { getType } from "./helpers/typeHelpers.js";
9
- import { toCamelCase } from "../utils/casingUtils.js";
10
- // ====== UTILITIES ======
11
- function isAzureCoreErrorSdkType(t) {
12
- return (t.name &&
13
- ["error", "errormodel", "innererror", "errorresponse"].includes(t.name.toLowerCase()) &&
14
- t.coreTypeInfo === "ErrorType");
9
+ import { extractPagedMetadataNested } from "../utils/operationUtil.js";
10
+ import { getTypeExpression, normalizeModelPropertyName } from "./type-expressions/get-type-expression.js";
11
+ import path from "path";
12
+ import { refkey } from "../framework/refkey.js";
13
+ import { useContext } from "../contextManager.js";
14
+ import { isMetadata } from "@typespec/http";
15
+ import { isAzureCoreErrorType, isAzureCoreLroType } from "../utils/modelUtils.js";
16
+ import { isExtensibleEnum } from "./type-expressions/get-enum-expression.js";
17
+ import { isDiscriminatedUnion } from "./serialization/serializeUtils.js";
18
+ import { reportDiagnostic } from "../lib.js";
19
+ import { NoTarget } from "@typespec/compiler";
20
+ import { emitQueue } from "../framework/hooks/sdkTypes.js";
21
+ function isGenerableType(type) {
22
+ return (type.kind === "model" ||
23
+ type.kind === "enum" ||
24
+ type.kind === "union" ||
25
+ type.kind === "dict" ||
26
+ type.kind === "array" ||
27
+ type.kind === "nullable");
15
28
  }
16
- function isAzureCoreLroSdkType(t) {
17
- return (t.name &&
18
- ["operationstate"].includes(t.name.toLowerCase()) &&
19
- t.coreTypeInfo === "LroType");
20
- }
21
- function isAnonymousModel(t) {
22
- return t.type === "model" && t.name === "";
23
- }
24
- export function isModelWithAdditionalProperties(t) {
25
- return t.type === "dict" && t.name !== "Record";
26
- }
27
- function getCoreClientErrorType(name, coreClientTypes) {
28
- const coreClientType = name === "Error" ? "ErrorModel" : name;
29
- coreClientTypes.add(coreClientType);
30
- return coreClientType;
31
- }
32
- function getCoreLroType(name, coreLroTypes) {
33
- const coreLroType = name === "OperationState" ? "CoreOperationStatus" : name;
34
- coreLroTypes.add(coreLroType);
35
- return coreLroType;
29
+ export function emitTypes(context, { sourceRoot }) {
30
+ const { sdkPackage } = context;
31
+ const outputProject = useContext("outputProject");
32
+ const modelsFilePath = getModelsPath(sourceRoot);
33
+ let sourceFile;
34
+ if (emitQueue.size > 0 &&
35
+ (sdkPackage.models.length > 0 || sdkPackage.enums.length > 0)) {
36
+ sourceFile = outputProject.createSourceFile(modelsFilePath);
37
+ if (!sourceFile) {
38
+ throw new Error(`Failed to create source file at ${modelsFilePath}`);
39
+ }
40
+ }
41
+ else {
42
+ return;
43
+ }
44
+ for (const type of emitQueue) {
45
+ if (!isGenerableType(type)) {
46
+ continue;
47
+ }
48
+ if (isAzureCoreLroType(type.__raw)) {
49
+ continue;
50
+ }
51
+ emitType(context, type, sourceFile);
52
+ }
53
+ if (sourceFile.getInterfaces().length === 0 &&
54
+ sourceFile.getTypeAliases().length === 0 &&
55
+ sourceFile.getEnums().length === 0) {
56
+ sourceFile.delete();
57
+ return;
58
+ }
59
+ addImportBySymbol("serializeRecord", sourceFile);
60
+ return sourceFile;
36
61
  }
37
- // ====== TYPE EXTRACTION ======
38
- function extractModels(codeModel) {
62
+ function emitType(context, type, sourceFile) {
39
63
  var _a;
40
- const models = codeModel.types.filter((t) => ((t.type === "model" || t.type === "enum") &&
41
- !isAzureCoreErrorSdkType(t) &&
42
- !isAzureCoreLroSdkType(t) &&
43
- !isAnonymousModel(t)) ||
44
- isModelWithAdditionalProperties(t));
45
- for (const model of codeModel.types) {
46
- if (model.type === "combined") {
47
- for (const unionModel of (_a = model.types) !== null && _a !== void 0 ? _a : []) {
48
- if (unionModel.type === "model") {
49
- models.push(unionModel);
50
- }
64
+ if (type.kind === "model") {
65
+ if (isAzureCoreErrorType(context.program, type.__raw)) {
66
+ return;
67
+ }
68
+ if (!type.usage ||
69
+ (type.usage !== undefined &&
70
+ (type.usage & UsageFlags.Output) !== UsageFlags.Output &&
71
+ (type.usage & UsageFlags.Input) !== UsageFlags.Input)) {
72
+ return;
73
+ }
74
+ if (!type.name && type.isGeneratedName) {
75
+ // TODO: https://github.com/Azure/typespec-azure/issues/1713 and https://github.com/microsoft/typespec/issues/4815
76
+ // throw new Error(`Generation of anonymous types`);
77
+ return;
78
+ }
79
+ const modelInterface = buildModelInterface(context, type);
80
+ if (type.discriminatorProperty) {
81
+ (_a = modelInterface.properties) === null || _a === void 0 ? void 0 : _a.filter((p) => {
82
+ return (p.name ===
83
+ normalizeModelPropertyName(context, type.discriminatorProperty));
84
+ }).map((p) => {
85
+ var _a, _b;
86
+ (_a = p.docs) === null || _a === void 0 ? void 0 : _a.push(`The discriminator possible values: ${Object.keys((_b = type.discriminatedSubtypes) !== null && _b !== void 0 ? _b : {}).join(", ")}`);
87
+ return p;
88
+ });
89
+ }
90
+ addDeclaration(sourceFile, modelInterface, type);
91
+ const modelPolymorphicType = buildModelPolymorphicType(context, type);
92
+ if (modelPolymorphicType) {
93
+ addSerializationFunctions(context, type, sourceFile, true);
94
+ addDeclaration(sourceFile, modelPolymorphicType, refkey(type, "polymorphicType"));
95
+ }
96
+ addSerializationFunctions(context, type, sourceFile);
97
+ }
98
+ else if (type.kind === "enum") {
99
+ if (!type.usage) {
100
+ return;
101
+ }
102
+ const apiVersionEnumOnly = type.usage === UsageFlags.ApiVersionEnum;
103
+ const inputUsage = (type.usage & UsageFlags.Input) === UsageFlags.Input;
104
+ const outputUsage = (type.usage & UsageFlags.Output) === UsageFlags.Output;
105
+ if (!(inputUsage || outputUsage || apiVersionEnumOnly)) {
106
+ return;
107
+ }
108
+ const [enumType, knownValuesEnum] = buildEnumTypes(context, type);
109
+ if (enumType.name.startsWith("_")) {
110
+ // skip enum generation for internal enums
111
+ return;
112
+ }
113
+ if (apiVersionEnumOnly) {
114
+ // generate known values enum only for api version enums
115
+ addDeclaration(sourceFile, knownValuesEnum, refkey(type, "knownValues"));
116
+ }
117
+ else {
118
+ if (isExtensibleEnum(context, type)) {
119
+ addDeclaration(sourceFile, knownValuesEnum, refkey(type, "knownValues"));
51
120
  }
121
+ addDeclaration(sourceFile, enumType, type);
52
122
  }
53
123
  }
54
- return models;
124
+ else if (type.kind === "union") {
125
+ const unionType = buildUnionType(context, type);
126
+ addDeclaration(sourceFile, unionType, type);
127
+ addSerializationFunctions(context, type, sourceFile);
128
+ }
129
+ else if (type.kind === "dict") {
130
+ addSerializationFunctions(context, type, sourceFile);
131
+ }
132
+ else if (type.kind === "array") {
133
+ addSerializationFunctions(context, type, sourceFile);
134
+ }
135
+ }
136
+ export function getApiVersionEnum(context) {
137
+ const apiVersionEnum = context.sdkPackage.enums.find((e) => e.usage === UsageFlags.ApiVersionEnum);
138
+ if (!apiVersionEnum) {
139
+ return;
140
+ }
141
+ return apiVersionEnum;
55
142
  }
56
- /**
57
- * Extracts all the aliases from the code model
58
- * 1. alias from polymorphic base model, where we need to use typescript union to combine all the sub models
59
- * 2. alias from unions, where we also need to use typescript union to combine all the union variants
60
- */
61
- export function extractAliases(codeModel) {
62
- const models = codeModel.types.filter((t) => ((t.type === "model" || t.type === "combined") &&
63
- t.alias &&
64
- t.aliasType) ||
65
- (isModelWithAdditionalProperties(t) && t.alias && t.aliasType));
66
- return models;
143
+ export function getModelsPath(sourceRoot) {
144
+ return path.join(...[sourceRoot, "models", `models.ts`]);
145
+ }
146
+ function addSerializationFunctions(context, type, sourceFile, skipDiscriminatedUnion = false) {
147
+ const serializationFunction = buildModelSerializer(context, type, skipDiscriminatedUnion);
148
+ if (serializationFunction &&
149
+ typeof serializationFunction !== "string" &&
150
+ serializationFunction.name &&
151
+ !sourceFile.getFunction(serializationFunction.name)) {
152
+ addDeclaration(sourceFile, serializationFunction, refkey(type, "serializer"));
153
+ }
154
+ const deserializationFunction = buildModelDeserializer(context, type, skipDiscriminatedUnion);
155
+ if (deserializationFunction &&
156
+ typeof deserializationFunction !== "string" &&
157
+ deserializationFunction.name &&
158
+ !sourceFile.getFunction(deserializationFunction.name)) {
159
+ addDeclaration(sourceFile, deserializationFunction, refkey(type, "deserializer"));
160
+ }
67
161
  }
68
- // ====== TYPE BUILDERS ======
69
- function buildEnumModel(model) {
162
+ function buildUnionType(context, type) {
70
163
  var _a;
71
- const valueType = ((_a = model.valueType) === null || _a === void 0 ? void 0 : _a.type) === "string" ? "string" : "number";
72
- return {
73
- name: model.name,
164
+ const unionDeclaration = {
165
+ kind: StructureKind.TypeAlias,
166
+ name: normalizeModelName(context, type),
74
167
  isExported: true,
75
- docs: [...getDocsFromDescription(model.description)],
76
- type: buildEnumType()
168
+ type: type.variantTypes
169
+ .map((v) => getTypeExpression(context, v))
170
+ .join(" | ")
77
171
  };
78
- function buildEnumType() {
79
- return model.isFixed || !model.isNonExhaustive
80
- ? getEnumValues(" | ")
81
- : valueType;
82
- }
83
- function getEnumValues(separator = ", ") {
84
- var _a;
85
- const splitWord = valueType === "string" ? `"` : ``;
86
- return ((_a = model.values) !== null && _a !== void 0 ? _a : [])
87
- .map((v) => `${splitWord}${v.value}${splitWord}`)
88
- .join(separator);
89
- }
172
+ unionDeclaration.docs = [(_a = type.doc) !== null && _a !== void 0 ? _a : `Alias for ${unionDeclaration.name}`];
173
+ return unionDeclaration;
90
174
  }
91
- export function buildModelInterface(model, cache) {
92
- var _a, _b, _c;
93
- const modelProperties = (_a = model.properties) !== null && _a !== void 0 ? _a : [];
94
- const modelInterface = {
95
- name: (_c = (_b = model.alias) !== null && _b !== void 0 ? _b : model.name) !== null && _c !== void 0 ? _c : "FIXMYNAME",
175
+ export function buildEnumTypes(context, type) {
176
+ var _a;
177
+ const enumDeclaration = {
178
+ kind: StructureKind.Enum,
179
+ name: `Known${normalizeModelName(context, type)}`,
96
180
  isExported: true,
97
- docs: getDocsFromDescription(model.description),
98
- extends: [],
99
- properties: (modelProperties !== null && modelProperties !== void 0 ? modelProperties : []).map((p) => {
100
- const propertyMetadata = getType(p.type, p.format);
101
- let propertyTypeName = propertyMetadata.name;
102
- if (isAzureCoreErrorSdkType(p.type)) {
103
- propertyTypeName = getCoreClientErrorType(propertyTypeName, cache.coreClientTypes);
104
- }
105
- if (isAzureCoreLroSdkType(p.type)) {
106
- propertyTypeName = getCoreLroType(propertyTypeName, cache.coreLroTypes);
107
- }
108
- return {
109
- name: `"${p.clientName}"`,
110
- docs: getDocsFromDescription(p.description),
111
- hasQuestionToken: p.optional,
112
- isReadonly: p.readonly,
113
- type: propertyTypeName
114
- };
115
- })
181
+ members: type.values.map(emitEnumMember)
116
182
  };
117
- return modelInterface;
118
- }
119
- // ====== MAIN FUNCTIONS ======
120
- /**
121
- * This function creates the file containing all the models defined in TypeSpec
122
- */
123
- export function buildModels(subClient, codeModel) {
124
- var _a, _b, _c;
125
- // We are generating both models and enums here
126
- const coreClientTypes = new Set();
127
- const coreLroTypes = new Set();
128
- // filter out the models/enums that are anonymous
129
- const models = extractModels(codeModel).filter((m) => !!m.name);
130
- const aliases = extractAliases(codeModel);
131
- // Skip to generate models.ts if there is no any models
132
- if (models.length === 0 && aliases.length === 0) {
133
- return;
134
- }
135
- const modelsFile = codeModel.project.createSourceFile(getModularModelFilePath(codeModel, subClient));
136
- for (const model of models) {
137
- if (model.type === "enum") {
138
- if (modelsFile.getTypeAlias(model.name)) {
139
- // If the enum is already defined, we don't need to do anything
140
- continue;
141
- }
142
- const enumAlias = buildEnumModel(model);
143
- if (model.isNonExhaustive && model.name) {
144
- modelsFile.addEnum({
145
- name: `Known${model.name}`,
146
- isExported: true,
147
- members: (_b = (_a = model.values) === null || _a === void 0 ? void 0 : _a.map((v) => ({
148
- name: v.name,
149
- value: v.value,
150
- docs: v.description ? [v.description] : [v.name]
151
- }))) !== null && _b !== void 0 ? _b : [],
152
- docs: [
153
- `Known values of {@link ${model.name}} that the service accepts.`
154
- ]
155
- });
156
- const description = getExtensibleEnumDescription(model);
157
- if (description) {
158
- enumAlias.docs = [description];
159
- }
160
- }
161
- modelsFile.addTypeAlias(enumAlias);
162
- }
163
- else {
164
- const modelInterface = buildModelInterface(model, {
165
- coreClientTypes,
166
- coreLroTypes
167
- });
168
- (_c = model.parents) === null || _c === void 0 ? void 0 : _c.forEach((p) => { var _a; return modelInterface.extends.push((_a = p.alias) !== null && _a !== void 0 ? _a : getType(p, p.format).name); });
169
- if (isModelWithAdditionalProperties(model)) {
170
- addExtendedDictInfo(model, modelInterface, codeModel.modularOptions.compatibilityMode);
171
- }
172
- if (!modelsFile.getInterface(modelInterface.name)) {
173
- modelsFile.addInterface(modelInterface);
174
- }
175
- // Generate a serializer function next to each model
176
- const serializerFunction = buildModelSerializer(model, codeModel.runtimeImports);
177
- if (serializerFunction &&
178
- !modelsFile.getFunction(toCamelCase(modelInterface.name + "Serializer"))) {
179
- modelsFile.addStatements(serializerFunction);
180
- }
181
- addImportBySymbol("serializeRecord", modelsFile);
182
- modelsFile.fixUnusedIdentifiers();
183
- }
184
- }
185
- const projectRootFromModels = codeModel.clients.length > 1 ? "../.." : "../";
186
- addImportsToFiles(codeModel.runtimeImports, modelsFile, {
187
- serializerHelpers: path.posix.join(projectRootFromModels, "helpers", "serializerHelpers.js")
188
- });
189
- if (coreClientTypes.size > 0) {
190
- modelsFile.addImportDeclarations([
191
- {
192
- moduleSpecifier: getImportSpecifier("restClient", codeModel.runtimeImports),
193
- namedImports: Array.from(coreClientTypes)
194
- }
195
- ]);
196
- }
197
- if (coreLroTypes.size > 0) {
198
- modelsFile.addImportDeclarations([
199
- {
200
- moduleSpecifier: getImportSpecifier("azureCoreLro", codeModel.runtimeImports),
201
- namedImports: Array.from(coreLroTypes).map((t) => t === "CoreOperationStatus"
202
- ? "OperationStatus as CoreOperationStatus"
203
- : t)
204
- }
205
- ]);
206
- }
207
- aliases.forEach((alias) => {
208
- modelsFile.addTypeAlias(buildModelTypeAlias(alias));
209
- if (!models.includes(alias)) {
210
- // Generate a serializer function next to each model
211
- const serializerFunction = buildModelSerializer(alias, codeModel.runtimeImports);
212
- if (serializerFunction) {
213
- modelsFile.addStatements(serializerFunction);
214
- }
215
- }
216
- });
217
- return modelsFile;
183
+ const enumAsUnion = {
184
+ kind: StructureKind.TypeAlias,
185
+ name: normalizeModelName(context, type),
186
+ isExported: true,
187
+ type: !isExtensibleEnum(context, type)
188
+ ? type.values.map((v) => getTypeExpression(context, v)).join(" | ")
189
+ : getTypeExpression(context, type.valueType)
190
+ };
191
+ const docs = type.doc ? type.doc : "Type of " + enumAsUnion.name;
192
+ enumAsUnion.docs =
193
+ isExtensibleEnum(context, type) && type.doc
194
+ ? [(_a = getExtensibleEnumDescription(type)) !== null && _a !== void 0 ? _a : docs]
195
+ : [docs];
196
+ enumDeclaration.docs = type.doc
197
+ ? [type.doc]
198
+ : [`Known values of {@link ${type.name}} that the service accepts.`];
199
+ return [enumAsUnion, enumDeclaration];
218
200
  }
219
201
  function getExtensibleEnumDescription(model) {
220
- if (!(model.isNonExhaustive && model.name && model.values)) {
202
+ if (model.isFixed && model.name && model.values) {
221
203
  return;
222
204
  }
223
205
  const valueDescriptions = model.values
224
- .map((v) => `**${v.value}**${v.description ? `: ${v.description}` : ""}`)
206
+ .map((v) => `**${v.value}**${v.doc ? `: ${v.doc}` : ""}`)
225
207
  .join(` \\\n`)
226
208
  // Escape the character / to make sure we don't incorrectly announce a comment blocks /** */
227
209
  .replace(/^\//g, "\\/")
228
210
  .replace(/([^\\])(\/)/g, "$1\\/");
229
211
  const enumLink = `{@link Known${model.name}} can be used interchangeably with ${model.name},\n this enum contains the known values that the service supports.`;
230
212
  return [
231
- `${model.description} \\`,
213
+ `${model.doc} \\`,
232
214
  enumLink,
233
215
  `### Known values supported by the service`,
234
216
  valueDescriptions
235
217
  ].join(" \n");
236
218
  }
237
- function addExtendedDictInfo(model, modelInterface, compatibilityMode = false) {
219
+ function emitEnumMember(member) {
220
+ const memberStructure = {
221
+ kind: StructureKind.EnumMember,
222
+ name: member.name,
223
+ value: member.value
224
+ };
225
+ if (member.doc) {
226
+ memberStructure.docs = [member.doc];
227
+ }
228
+ return memberStructure;
229
+ }
230
+ export function buildModelInterface(context, type) {
231
+ var _a;
232
+ const interfaceStructure = {
233
+ kind: StructureKind.Interface,
234
+ name: normalizeModelName(context, type, NameType.Interface, true),
235
+ isExported: true,
236
+ properties: type.properties
237
+ .filter((p) => !isMetadata(context.program, p.__raw))
238
+ .map((p) => {
239
+ return buildModelProperty(context, p);
240
+ })
241
+ };
242
+ if (type.baseModel) {
243
+ const parentReference = getModelExpression(context, type.baseModel, {
244
+ skipPolymorphicUnion: true
245
+ });
246
+ interfaceStructure.extends = [parentReference];
247
+ }
248
+ if (type.additionalProperties) {
249
+ addExtendedDictInfo(context, type, interfaceStructure);
250
+ }
251
+ interfaceStructure.docs = [
252
+ (_a = type.doc) !== null && _a !== void 0 ? _a : "model interface " + interfaceStructure.name
253
+ ];
254
+ return interfaceStructure;
255
+ }
256
+ function addExtendedDictInfo(context, model, modelInterface) {
238
257
  var _a, _b, _c, _d, _e;
258
+ const additionalPropertiesType = model.additionalProperties
259
+ ? getTypeExpression(context, model.additionalProperties)
260
+ : undefined;
239
261
  if ((model.properties &&
240
262
  model.properties.length > 0 &&
241
- model.elementType &&
263
+ model.additionalProperties &&
242
264
  ((_a = model.properties) === null || _a === void 0 ? void 0 : _a.every((p) => {
243
- var _a;
244
- return (_a = getType(model.elementType)) === null || _a === void 0 ? void 0 : _a.name.includes(getType(p.type).name);
265
+ return additionalPropertiesType === null || additionalPropertiesType === void 0 ? void 0 : additionalPropertiesType.includes(getTypeExpression(context, p.type));
245
266
  }))) ||
246
- (((_b = model.properties) === null || _b === void 0 ? void 0 : _b.length) === 0 && model.elementType)) {
247
- modelInterface.extends.push(`Record<string, ${(_c = getType(model.elementType).name) !== null && _c !== void 0 ? _c : "any"}>`);
267
+ (((_b = model.properties) === null || _b === void 0 ? void 0 : _b.length) === 0 && model.additionalProperties)) {
268
+ modelInterface.extends = [
269
+ ...((_c = modelInterface.extends) !== null && _c !== void 0 ? _c : []),
270
+ `Record<string, ${additionalPropertiesType !== null && additionalPropertiesType !== void 0 ? additionalPropertiesType : "any"}>`
271
+ ];
248
272
  }
249
- else if (compatibilityMode) {
273
+ else if ((_d = context.rlcOptions) === null || _d === void 0 ? void 0 : _d.compatibilityMode) {
274
+ if (!modelInterface.extends) {
275
+ modelInterface.extends = [];
276
+ }
250
277
  modelInterface.extends.push(`Record<string, any>`);
251
278
  }
252
279
  else {
253
- (_d = modelInterface.properties) === null || _d === void 0 ? void 0 : _d.push({
280
+ (_e = modelInterface.properties) === null || _e === void 0 ? void 0 : _e.push({
254
281
  name: "additionalProperties",
255
282
  docs: ["Additional properties"],
256
283
  hasQuestionToken: true,
257
284
  isReadonly: false,
258
- type: `Record<string, ${(_e = getType(model.elementType).name) !== null && _e !== void 0 ? _e : "any"}>`
285
+ type: `Record<string, ${additionalPropertiesType !== null && additionalPropertiesType !== void 0 ? additionalPropertiesType : "any"}>`
259
286
  });
260
287
  }
261
288
  }
262
- export function buildModelTypeAlias(model) {
263
- return {
264
- name: model.name,
289
+ export function normalizeModelName(context, type, nameType = NameType.Interface, skipPolymorphicUnionSuffix = false) {
290
+ var _a;
291
+ if (type.kind === "array") {
292
+ return `Array<${normalizeModelName(context, type.valueType, nameType)}>`;
293
+ }
294
+ else if (type.kind === "dict") {
295
+ return `Record<string, ${normalizeModelName(context, type.valueType, nameType)}>`;
296
+ }
297
+ if (type.kind !== "model" && type.kind !== "enum" && type.kind !== "union") {
298
+ return getTypeExpression(context, type);
299
+ }
300
+ const segments = type.crossLanguageDefinitionId.split(".");
301
+ segments.pop();
302
+ segments.shift();
303
+ segments.filter((segment) => segment !== context.sdkPackage.rootNamespace);
304
+ let unionSuffix = "";
305
+ if (!skipPolymorphicUnionSuffix) {
306
+ if (type.kind === "model" && isDiscriminatedUnion(type)) {
307
+ unionSuffix = "Union";
308
+ }
309
+ }
310
+ const namespacePrefix = ((_a = context.rlcOptions) === null || _a === void 0 ? void 0 : _a.enableModelNamespace)
311
+ ? segments.join("")
312
+ : "";
313
+ let internalModelPrefix = "";
314
+ if (type.__raw && type.__raw.kind === "Model") {
315
+ // TODO: this is temporary until we have a better way in tcgc to extract the paged metadata
316
+ // issue link https://github.com/Azure/typespec-azure/issues/1464
317
+ const page = extractPagedMetadataNested(context.program, type.__raw);
318
+ internalModelPrefix =
319
+ page && page.itemsSegments && page.itemsSegments.length > 0 ? "_" : "";
320
+ }
321
+ if (type.isGeneratedName) {
322
+ internalModelPrefix = "_";
323
+ }
324
+ return `${internalModelPrefix}${normalizeName(namespacePrefix + type.name + unionSuffix, nameType, true)}`;
325
+ }
326
+ function buildModelPolymorphicType(context, type) {
327
+ if (!type.discriminatedSubtypes) {
328
+ return undefined;
329
+ }
330
+ const discriminatedSubtypes = Object.values(type.discriminatedSubtypes);
331
+ const typeDeclaration = {
332
+ kind: StructureKind.TypeAlias,
333
+ name: `${normalizeName(type.name, NameType.Interface)}Union`,
265
334
  isExported: true,
266
- docs: ["Alias for " + model.name],
267
- type: model.aliasType
335
+ type: discriminatedSubtypes
336
+ .filter((p) => {
337
+ return (p.usage !== undefined &&
338
+ ((p.usage & UsageFlags.Output) === UsageFlags.Output ||
339
+ (p.usage & UsageFlags.Input) === UsageFlags.Input));
340
+ })
341
+ .map((t) => getTypeExpression(context, t))
342
+ .join(" | ")
268
343
  };
344
+ typeDeclaration.docs = [`Alias for ${typeDeclaration.name}`];
345
+ typeDeclaration.type += ` | ${getModelExpression(context, type, {
346
+ skipPolymorphicUnion: true
347
+ })}`;
348
+ return typeDeclaration;
269
349
  }
270
- export function buildModelsOptions(client, codeModel) {
350
+ function buildModelProperty(context, property) {
271
351
  var _a;
272
- const modelOptionsFile = codeModel.project.createSourceFile(path.join(codeModel.modularOptions.sourceRoot, (_a = client.subfolder) !== null && _a !== void 0 ? _a : "", `models/options.ts`), undefined, {
273
- overwrite: true
274
- });
275
- for (const operationGroup of client.operationGroups) {
276
- operationGroup.operations.forEach((o) => {
277
- buildOperationOptions(o, modelOptionsFile);
352
+ const normalizedPropName = normalizeModelPropertyName(context, property);
353
+ if (!((_a = context.rlcOptions) === null || _a === void 0 ? void 0 : _a.ignorePropertyNameNormalize) &&
354
+ normalizedPropName !== `"${property.name}"`) {
355
+ reportDiagnostic(context.program, {
356
+ code: "property-name-normalized",
357
+ format: {
358
+ propertyName: property.name,
359
+ normalizedName: normalizedPropName
360
+ },
361
+ target: NoTarget
278
362
  });
279
363
  }
280
- modelOptionsFile.addImportDeclarations([
281
- {
282
- moduleSpecifier: getImportSpecifier("restClient", codeModel.runtimeImports),
283
- namedImports: ["OperationOptions"]
364
+ const propertyStructure = {
365
+ kind: StructureKind.PropertySignature,
366
+ name: normalizedPropName,
367
+ type: getTypeExpression(context, property.type),
368
+ hasQuestionToken: property.optional,
369
+ isReadonly: isReadOnly(property)
370
+ };
371
+ if (property.doc) {
372
+ propertyStructure.docs = [property.doc];
373
+ }
374
+ return propertyStructure;
375
+ }
376
+ export function visitPackageTypes(context) {
377
+ const { sdkPackage } = context;
378
+ emitQueue.clear();
379
+ // Add all models in the package to the emit queue
380
+ for (const model of sdkPackage.models) {
381
+ visitType(context, model);
382
+ }
383
+ for (const union of sdkPackage.unions) {
384
+ visitType(context, union);
385
+ }
386
+ // Add all enums to the queue
387
+ for (const enumType of sdkPackage.enums) {
388
+ if (!emitQueue.has(enumType)) {
389
+ emitQueue.add(enumType);
284
390
  }
285
- ]);
286
- modelOptionsFile
287
- .getImportDeclarations()
288
- .filter((id) => {
289
- return (id.isModuleSpecifierRelative() &&
290
- !id.getModuleSpecifierValue().endsWith(".js"));
291
- })
292
- .map((id) => {
293
- id.setModuleSpecifier(id.getModuleSpecifierValue() + ".js");
294
- return id;
391
+ }
392
+ // Visit the clients to discover all models
393
+ for (const client of sdkPackage.clients) {
394
+ visitClient(context, client);
395
+ }
396
+ }
397
+ function visitClient(context, client) {
398
+ // Comment this out for now, as client initialization is not used in the generated code
399
+ // visitType(client.initialization, emitQueue);
400
+ client.methods.forEach((method) => visitClientMethod(context, method));
401
+ }
402
+ function visitClientMethod(context, method) {
403
+ switch (method.kind) {
404
+ case "lro":
405
+ case "paging":
406
+ case "lropaging":
407
+ case "basic":
408
+ visitMethod(context, method);
409
+ visitOperation(context, method.operation);
410
+ break;
411
+ case "clientaccessor":
412
+ method.response.methods.forEach((responseMethod) => visitClientMethod(context, responseMethod));
413
+ method.parameters.forEach((parameter) => {
414
+ visitType(context, parameter.type);
415
+ });
416
+ break;
417
+ default:
418
+ throw new Error(`Unknown sdk method kind: ${method.kind}`);
419
+ }
420
+ }
421
+ function visitOperation(context, operation) {
422
+ var _a;
423
+ // Visit the request
424
+ visitType(context, (_a = operation.bodyParam) === null || _a === void 0 ? void 0 : _a.type);
425
+ // Visit the response
426
+ operation.exceptions.forEach((exception) => visitType(context, exception.type));
427
+ operation.parameters.forEach((parameter) => {
428
+ visitType(context, parameter.type);
429
+ });
430
+ operation.responses.forEach((response) => visitType(context, response.type));
431
+ }
432
+ function visitMethod(context, method) {
433
+ // Visit the request
434
+ method.parameters.forEach((parameter) => {
435
+ visitType(context, parameter.type);
295
436
  });
296
- return modelOptionsFile;
437
+ visitType(context, method.response.type);
438
+ }
439
+ function visitType(context, type) {
440
+ if (!type) {
441
+ return;
442
+ }
443
+ if (emitQueue.has(type)) {
444
+ return;
445
+ }
446
+ emitQueue.add(type);
447
+ if (type.kind === "model") {
448
+ const externalModel = getExternalModel(type);
449
+ if (externalModel) {
450
+ return;
451
+ }
452
+ if (type.additionalProperties) {
453
+ visitType(context, type.additionalProperties);
454
+ }
455
+ for (const property of type.properties) {
456
+ if (!emitQueue.has(property.type)) {
457
+ visitType(context, property.type);
458
+ }
459
+ }
460
+ if (type.discriminatedSubtypes) {
461
+ for (const subType of Object.values(type.discriminatedSubtypes)) {
462
+ if (!emitQueue.has(subType)) {
463
+ visitType(context, subType);
464
+ }
465
+ }
466
+ }
467
+ }
468
+ if (type.kind === "array") {
469
+ if (!emitQueue.has(type.valueType)) {
470
+ visitType(context, type.valueType);
471
+ }
472
+ }
473
+ if (type.kind === "dict") {
474
+ if (!emitQueue.has(type.valueType)) {
475
+ visitType(context, type.valueType);
476
+ }
477
+ }
478
+ if (type.kind === "union") {
479
+ emitQueue.add(type);
480
+ for (const value of type.variantTypes) {
481
+ if (!emitQueue.has(value)) {
482
+ visitType(context, value);
483
+ }
484
+ }
485
+ }
486
+ if (type.kind === "nullable") {
487
+ emitQueue.add(type);
488
+ if (!emitQueue.has(type.type)) {
489
+ visitType(context, type.type);
490
+ }
491
+ }
297
492
  }
298
493
  //# sourceMappingURL=emitModels.js.map