@typespec/http-server-csharp 0.58.0-alpha.28-dev.4 → 0.58.0-alpha.29-dev.3

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 (279) hide show
  1. package/dist/src/cli/cli.js +118 -154
  2. package/dist/src/cli/cli.js.map +1 -1
  3. package/dist/src/components/controller-action/controller-action.d.ts +16 -0
  4. package/dist/src/components/controller-action/controller-action.d.ts.map +1 -0
  5. package/dist/src/components/controller-action/controller-action.js +251 -0
  6. package/dist/src/components/controller-action/controller-action.js.map +1 -0
  7. package/dist/src/components/controller-action/controller-action.test.d.ts +2 -0
  8. package/dist/src/components/controller-action/controller-action.test.d.ts.map +1 -0
  9. package/dist/src/components/controller-action/controller-action.test.js +106 -0
  10. package/dist/src/components/controller-action/controller-action.test.js.map +1 -0
  11. package/dist/src/components/controller-action/parameter-binding.d.ts +17 -0
  12. package/dist/src/components/controller-action/parameter-binding.d.ts.map +1 -0
  13. package/dist/src/components/controller-action/parameter-binding.js +77 -0
  14. package/dist/src/components/controller-action/parameter-binding.js.map +1 -0
  15. package/dist/src/components/controller-action/response-analysis.d.ts +10 -0
  16. package/dist/src/components/controller-action/response-analysis.d.ts.map +1 -0
  17. package/dist/src/components/controller-action/response-analysis.js +61 -0
  18. package/dist/src/components/controller-action/response-analysis.js.map +1 -0
  19. package/dist/src/components/controllers/controllers.d.ts +18 -0
  20. package/dist/src/components/controllers/controllers.d.ts.map +1 -0
  21. package/dist/src/components/controllers/controllers.js +64 -0
  22. package/dist/src/components/controllers/controllers.js.map +1 -0
  23. package/dist/src/components/controllers/controllers.test.d.ts +2 -0
  24. package/dist/src/components/controllers/controllers.test.d.ts.map +1 -0
  25. package/dist/src/components/controllers/controllers.test.js +84 -0
  26. package/dist/src/components/controllers/controllers.test.js.map +1 -0
  27. package/dist/src/components/csharp-file.d.ts +15 -0
  28. package/dist/src/components/csharp-file.d.ts.map +1 -0
  29. package/dist/src/components/csharp-file.js +28 -0
  30. package/dist/src/components/csharp-file.js.map +1 -0
  31. package/dist/src/components/enums/enums.d.ts +28 -0
  32. package/dist/src/components/enums/enums.d.ts.map +1 -0
  33. package/dist/src/components/enums/enums.js +158 -0
  34. package/dist/src/components/enums/enums.js.map +1 -0
  35. package/dist/src/components/enums/enums.test.d.ts +2 -0
  36. package/dist/src/components/enums/enums.test.d.ts.map +1 -0
  37. package/dist/src/components/enums/enums.test.js +112 -0
  38. package/dist/src/components/enums/enums.test.js.map +1 -0
  39. package/dist/src/components/interfaces/interfaces.d.ts +17 -0
  40. package/dist/src/components/interfaces/interfaces.d.ts.map +1 -0
  41. package/dist/src/components/interfaces/interfaces.js +153 -0
  42. package/dist/src/components/interfaces/interfaces.js.map +1 -0
  43. package/dist/src/components/interfaces/interfaces.test.d.ts +2 -0
  44. package/dist/src/components/interfaces/interfaces.test.d.ts.map +1 -0
  45. package/dist/src/components/interfaces/interfaces.test.js +76 -0
  46. package/dist/src/components/interfaces/interfaces.test.js.map +1 -0
  47. package/dist/src/components/models/anonymous-models.d.ts +9 -0
  48. package/dist/src/components/models/anonymous-models.d.ts.map +1 -0
  49. package/dist/src/components/models/anonymous-models.js +37 -0
  50. package/dist/src/components/models/anonymous-models.js.map +1 -0
  51. package/dist/src/components/models/error-models.d.ts +5 -0
  52. package/dist/src/components/models/error-models.d.ts.map +1 -0
  53. package/dist/src/components/models/error-models.js +84 -0
  54. package/dist/src/components/models/error-models.js.map +1 -0
  55. package/dist/src/components/models/model-helpers.d.ts +40 -0
  56. package/dist/src/components/models/model-helpers.d.ts.map +1 -0
  57. package/dist/src/components/models/model-helpers.js +239 -0
  58. package/dist/src/components/models/model-helpers.js.map +1 -0
  59. package/dist/src/components/models/models.d.ts +15 -0
  60. package/dist/src/components/models/models.d.ts.map +1 -0
  61. package/dist/src/components/models/models.js +234 -0
  62. package/dist/src/components/models/models.js.map +1 -0
  63. package/dist/src/components/models/models.test.d.ts +2 -0
  64. package/dist/src/components/models/models.test.d.ts.map +1 -0
  65. package/dist/src/components/models/models.test.js +151 -0
  66. package/dist/src/components/models/models.test.js.map +1 -0
  67. package/dist/src/components/project/csproj.d.ts +12 -0
  68. package/dist/src/components/project/csproj.d.ts.map +1 -0
  69. package/dist/src/components/project/csproj.js +35 -0
  70. package/dist/src/components/project/csproj.js.map +1 -0
  71. package/dist/src/components/project/csproj.test.d.ts +2 -0
  72. package/dist/src/components/project/csproj.test.d.ts.map +1 -0
  73. package/dist/src/components/project/csproj.test.js +42 -0
  74. package/dist/src/components/project/csproj.test.js.map +1 -0
  75. package/dist/src/components/project/launch-settings.d.ts +16 -0
  76. package/dist/src/components/project/launch-settings.d.ts.map +1 -0
  77. package/dist/src/components/project/launch-settings.js +73 -0
  78. package/dist/src/components/project/launch-settings.js.map +1 -0
  79. package/dist/src/components/project/launch-settings.test.d.ts +2 -0
  80. package/dist/src/components/project/launch-settings.test.d.ts.map +1 -0
  81. package/dist/src/components/project/launch-settings.test.js +48 -0
  82. package/dist/src/components/project/launch-settings.test.js.map +1 -0
  83. package/dist/src/components/project/program.d.ts +14 -0
  84. package/dist/src/components/project/program.d.ts.map +1 -0
  85. package/dist/src/components/project/program.js +75 -0
  86. package/dist/src/components/project/program.js.map +1 -0
  87. package/dist/src/components/project/program.test.d.ts +2 -0
  88. package/dist/src/components/project/program.test.d.ts.map +1 -0
  89. package/dist/src/components/project/program.test.js +50 -0
  90. package/dist/src/components/project/program.test.js.map +1 -0
  91. package/dist/src/components/render-root.d.ts +14 -0
  92. package/dist/src/components/render-root.d.ts.map +1 -0
  93. package/dist/src/components/render-root.js +122 -0
  94. package/dist/src/components/render-root.js.map +1 -0
  95. package/dist/src/components/request-models.d.ts +15 -0
  96. package/dist/src/components/request-models.d.ts.map +1 -0
  97. package/dist/src/components/request-models.js +97 -0
  98. package/dist/src/components/request-models.js.map +1 -0
  99. package/dist/src/components/scaffolding/documentation.d.ts +12 -0
  100. package/dist/src/components/scaffolding/documentation.d.ts.map +1 -0
  101. package/dist/src/{lib/doc.js → components/scaffolding/documentation.js} +56 -46
  102. package/dist/src/components/scaffolding/documentation.js.map +1 -0
  103. package/dist/src/components/scaffolding/mock-helpers.d.ts +10 -0
  104. package/dist/src/components/scaffolding/mock-helpers.d.ts.map +1 -0
  105. package/dist/src/components/scaffolding/mock-helpers.js +268 -0
  106. package/dist/src/components/scaffolding/mock-helpers.js.map +1 -0
  107. package/dist/src/components/scaffolding/mock-implementations.d.ts +14 -0
  108. package/dist/src/components/scaffolding/mock-implementations.d.ts.map +1 -0
  109. package/dist/src/components/scaffolding/mock-implementations.js +152 -0
  110. package/dist/src/components/scaffolding/mock-implementations.js.map +1 -0
  111. package/dist/src/components/scaffolding/mock-return-utils.d.ts +11 -0
  112. package/dist/src/components/scaffolding/mock-return-utils.d.ts.map +1 -0
  113. package/dist/src/components/scaffolding/mock-return-utils.js +62 -0
  114. package/dist/src/components/scaffolding/mock-return-utils.js.map +1 -0
  115. package/dist/src/components/scaffolding/mock-scaffolding.d.ts +6 -0
  116. package/dist/src/components/scaffolding/mock-scaffolding.d.ts.map +1 -0
  117. package/dist/src/components/scaffolding/mock-scaffolding.js +5 -0
  118. package/dist/src/components/scaffolding/mock-scaffolding.js.map +1 -0
  119. package/dist/src/components/scaffolding/mock-scaffolding.test.d.ts +2 -0
  120. package/dist/src/components/scaffolding/mock-scaffolding.test.d.ts.map +1 -0
  121. package/dist/src/components/scaffolding/mock-scaffolding.test.js +59 -0
  122. package/dist/src/components/scaffolding/mock-scaffolding.test.js.map +1 -0
  123. package/dist/src/components/serialization/base64-url-json-converter.d.ts +7 -0
  124. package/dist/src/components/serialization/base64-url-json-converter.d.ts.map +1 -0
  125. package/dist/src/components/serialization/base64-url-json-converter.js +58 -0
  126. package/dist/src/components/serialization/base64-url-json-converter.js.map +1 -0
  127. package/dist/src/components/serialization/constraint-attributes.d.ts +7 -0
  128. package/dist/src/components/serialization/constraint-attributes.d.ts.map +1 -0
  129. package/dist/src/components/serialization/constraint-attributes.js +556 -0
  130. package/dist/src/components/serialization/constraint-attributes.js.map +1 -0
  131. package/dist/src/components/serialization/http-service-exception-filter.d.ts +8 -0
  132. package/dist/src/components/serialization/http-service-exception-filter.d.ts.map +1 -0
  133. package/dist/src/components/serialization/http-service-exception-filter.js +71 -0
  134. package/dist/src/components/serialization/http-service-exception-filter.js.map +1 -0
  135. package/dist/src/components/serialization/json-converters.d.ts +7 -0
  136. package/dist/src/components/serialization/json-converters.d.ts.map +1 -0
  137. package/dist/src/components/serialization/json-converters.js +22 -0
  138. package/dist/src/components/serialization/json-converters.js.map +1 -0
  139. package/dist/src/components/serialization/json-converters.test.d.ts +2 -0
  140. package/dist/src/components/serialization/json-converters.test.d.ts.map +1 -0
  141. package/dist/src/components/serialization/json-converters.test.js +136 -0
  142. package/dist/src/components/serialization/json-converters.test.js.map +1 -0
  143. package/dist/src/components/serialization/json-serialization-provider.d.ts +7 -0
  144. package/dist/src/components/serialization/json-serialization-provider.d.ts.map +1 -0
  145. package/dist/src/components/serialization/json-serialization-provider.js +90 -0
  146. package/dist/src/components/serialization/json-serialization-provider.js.map +1 -0
  147. package/dist/src/components/serialization/time-span-duration-converter.d.ts +7 -0
  148. package/dist/src/components/serialization/time-span-duration-converter.d.ts.map +1 -0
  149. package/dist/src/components/serialization/time-span-duration-converter.js +44 -0
  150. package/dist/src/components/serialization/time-span-duration-converter.js.map +1 -0
  151. package/dist/src/components/serialization/unix-epoch-date-time-converter.d.ts +7 -0
  152. package/dist/src/components/serialization/unix-epoch-date-time-converter.d.ts.map +1 -0
  153. package/dist/src/components/serialization/unix-epoch-date-time-converter.js +71 -0
  154. package/dist/src/components/serialization/unix-epoch-date-time-converter.js.map +1 -0
  155. package/dist/src/components/type-expression/type-expression.d.ts +24 -0
  156. package/dist/src/components/type-expression/type-expression.d.ts.map +1 -0
  157. package/dist/src/components/type-expression/type-expression.js +223 -0
  158. package/dist/src/components/type-expression/type-expression.js.map +1 -0
  159. package/dist/src/components/type-expression/type-expression.test.d.ts +2 -0
  160. package/dist/src/components/type-expression/type-expression.test.d.ts.map +1 -0
  161. package/dist/src/components/type-expression/type-expression.test.js +207 -0
  162. package/dist/src/components/type-expression/type-expression.test.js.map +1 -0
  163. package/dist/src/context/emitter-options-context.d.ts +13 -0
  164. package/dist/src/context/emitter-options-context.d.ts.map +1 -0
  165. package/dist/src/context/emitter-options-context.js +15 -0
  166. package/dist/src/context/emitter-options-context.js.map +1 -0
  167. package/dist/src/diagnostics.d.ts +8 -0
  168. package/dist/src/diagnostics.d.ts.map +1 -0
  169. package/dist/src/diagnostics.js +164 -0
  170. package/dist/src/diagnostics.js.map +1 -0
  171. package/dist/src/emitter.d.ts +8 -0
  172. package/dist/src/emitter.d.ts.map +1 -0
  173. package/dist/src/emitter.js +180 -0
  174. package/dist/src/emitter.js.map +1 -0
  175. package/dist/src/{lib/index.d.ts → index.d.ts} +1 -1
  176. package/dist/src/index.d.ts.map +1 -0
  177. package/dist/src/{lib/index.js → index.js} +1 -1
  178. package/dist/src/index.js.map +1 -0
  179. package/dist/src/{lib/lib.d.ts → lib.d.ts} +4 -14
  180. package/dist/src/lib.d.ts.map +1 -0
  181. package/dist/src/lib.js +133 -0
  182. package/dist/src/lib.js.map +1 -0
  183. package/dist/src/output-writer.d.ts +11 -0
  184. package/dist/src/output-writer.d.ts.map +1 -0
  185. package/dist/src/output-writer.js +72 -0
  186. package/dist/src/output-writer.js.map +1 -0
  187. package/dist/src/service-discovery.d.ts +13 -0
  188. package/dist/src/service-discovery.d.ts.map +1 -0
  189. package/dist/src/service-discovery.js +93 -0
  190. package/dist/src/service-discovery.js.map +1 -0
  191. package/dist/src/service-resolution.d.ts +34 -0
  192. package/dist/src/service-resolution.d.ts.map +1 -0
  193. package/dist/src/service-resolution.js +244 -0
  194. package/dist/src/service-resolution.js.map +1 -0
  195. package/dist/src/testing/index.d.ts +2 -0
  196. package/dist/src/testing/index.d.ts.map +1 -0
  197. package/dist/src/testing/index.js +2 -0
  198. package/dist/src/testing/index.js.map +1 -0
  199. package/dist/src/utils/attributes.d.ts +8 -0
  200. package/dist/src/utils/attributes.d.ts.map +1 -0
  201. package/dist/src/utils/attributes.js +224 -0
  202. package/dist/src/utils/attributes.js.map +1 -0
  203. package/dist/src/utils/csharp-libs.d.ts +87 -0
  204. package/dist/src/utils/csharp-libs.d.ts.map +1 -0
  205. package/dist/src/utils/csharp-libs.js +90 -0
  206. package/dist/src/utils/csharp-libs.js.map +1 -0
  207. package/dist/src/utils/doc-comments.d.ts +2 -0
  208. package/dist/src/utils/doc-comments.d.ts.map +1 -0
  209. package/dist/src/utils/doc-comments.js +4 -0
  210. package/dist/src/utils/doc-comments.js.map +1 -0
  211. package/dist/src/utils/http-helpers.d.ts +19 -0
  212. package/dist/src/utils/http-helpers.d.ts.map +1 -0
  213. package/dist/src/utils/http-helpers.js +70 -0
  214. package/dist/src/utils/http-helpers.js.map +1 -0
  215. package/dist/src/utils/http-helpers.test.d.ts +2 -0
  216. package/dist/src/utils/http-helpers.test.d.ts.map +1 -0
  217. package/dist/src/utils/http-helpers.test.js +68 -0
  218. package/dist/src/utils/http-helpers.test.js.map +1 -0
  219. package/dist/src/utils/namespace-utils.d.ts +13 -0
  220. package/dist/src/utils/namespace-utils.d.ts.map +1 -0
  221. package/dist/src/utils/namespace-utils.js +55 -0
  222. package/dist/src/utils/namespace-utils.js.map +1 -0
  223. package/dist/src/utils/naming.d.ts +31 -0
  224. package/dist/src/utils/naming.d.ts.map +1 -0
  225. package/dist/src/utils/naming.js +87 -0
  226. package/dist/src/utils/naming.js.map +1 -0
  227. package/dist/src/utils/naming.test.d.ts +2 -0
  228. package/dist/src/utils/naming.test.d.ts.map +1 -0
  229. package/dist/src/utils/naming.test.js +86 -0
  230. package/dist/src/utils/naming.test.js.map +1 -0
  231. package/dist/src/utils/port.d.ts +5 -0
  232. package/dist/src/utils/port.d.ts.map +1 -0
  233. package/dist/src/utils/port.js +33 -0
  234. package/dist/src/utils/port.js.map +1 -0
  235. package/dist/src/utils/return-type-helpers.d.ts +8 -0
  236. package/dist/src/utils/return-type-helpers.d.ts.map +1 -0
  237. package/dist/src/utils/return-type-helpers.js +59 -0
  238. package/dist/src/utils/return-type-helpers.js.map +1 -0
  239. package/package.json +34 -26
  240. package/dist/src/lib/attributes.d.ts +0 -43
  241. package/dist/src/lib/attributes.d.ts.map +0 -1
  242. package/dist/src/lib/attributes.js +0 -422
  243. package/dist/src/lib/attributes.js.map +0 -1
  244. package/dist/src/lib/boilerplate.d.ts +0 -6
  245. package/dist/src/lib/boilerplate.d.ts.map +0 -1
  246. package/dist/src/lib/boilerplate.js +0 -792
  247. package/dist/src/lib/boilerplate.js.map +0 -1
  248. package/dist/src/lib/doc.d.ts +0 -5
  249. package/dist/src/lib/doc.d.ts.map +0 -1
  250. package/dist/src/lib/doc.js.map +0 -1
  251. package/dist/src/lib/index.d.ts.map +0 -1
  252. package/dist/src/lib/index.js.map +0 -1
  253. package/dist/src/lib/interfaces.d.ts +0 -183
  254. package/dist/src/lib/interfaces.d.ts.map +0 -1
  255. package/dist/src/lib/interfaces.js +0 -287
  256. package/dist/src/lib/interfaces.js.map +0 -1
  257. package/dist/src/lib/lib.d.ts.map +0 -1
  258. package/dist/src/lib/lib.js +0 -146
  259. package/dist/src/lib/lib.js.map +0 -1
  260. package/dist/src/lib/project.d.ts +0 -5
  261. package/dist/src/lib/project.d.ts.map +0 -1
  262. package/dist/src/lib/project.js +0 -101
  263. package/dist/src/lib/project.js.map +0 -1
  264. package/dist/src/lib/scaffolding.d.ts +0 -22
  265. package/dist/src/lib/scaffolding.d.ts.map +0 -1
  266. package/dist/src/lib/scaffolding.js +0 -461
  267. package/dist/src/lib/scaffolding.js.map +0 -1
  268. package/dist/src/lib/service.d.ts +0 -4
  269. package/dist/src/lib/service.d.ts.map +0 -1
  270. package/dist/src/lib/service.js +0 -1208
  271. package/dist/src/lib/service.js.map +0 -1
  272. package/dist/src/lib/type-helpers.d.ts +0 -44
  273. package/dist/src/lib/type-helpers.d.ts.map +0 -1
  274. package/dist/src/lib/type-helpers.js +0 -106
  275. package/dist/src/lib/type-helpers.js.map +0 -1
  276. package/dist/src/lib/utils.d.ts +0 -120
  277. package/dist/src/lib/utils.d.ts.map +0 -1
  278. package/dist/src/lib/utils.js +0 -1580
  279. package/dist/src/lib/utils.js.map +0 -1
@@ -1,1208 +0,0 @@
1
- import { CodeTypeEmitter, StringBuilder, code, createAssetEmitter, } from "@typespec/asset-emitter";
2
- import { getDoc, getNamespaceFullName, getService, isErrorModel, isNeverType, isNullType, isNumericType, isTemplateDeclaration, isVoidType, resolvePath, serializeValueAsJson, } from "@typespec/compiler";
3
- import { createRekeyableMap } from "@typespec/compiler/utils";
4
- import { getHeaderFieldName, getHttpOperation, getHttpPart, isHeader, isStatusCode, } from "@typespec/http";
5
- import { getUniqueItems } from "@typespec/json-schema";
6
- import { getResourceOperation } from "@typespec/rest";
7
- import { execFile } from "child_process";
8
- import path from "path";
9
- import { getEncodedNameAttribute } from "./attributes.js";
10
- import { GeneratedFileHeader, GeneratedFileHeaderWithNullable, getSerializationSourceFiles, } from "./boilerplate.js";
11
- import { getProjectDocs } from "./doc.js";
12
- import { CSharpSourceType, CSharpType, CollectionType, NameCasingType, checkOrAddNamespaceToScope, } from "./interfaces.js";
13
- import { CSharpServiceOptions, reportDiagnostic } from "./lib.js";
14
- import { getProjectHelpers } from "./project.js";
15
- import { getBusinessLogicImplementations, getScaffoldingHelpers, } from "./scaffolding.js";
16
- import { getEnumType, getRecordType, isKnownReferenceType } from "./type-helpers.js";
17
- import { CSharpOperationHelpers, HttpMetadata, ModelInfo, UnknownType, coalesceTypes, coalesceUnionTypes, ensureCSharpIdentifier, ensureCleanDirectory, formatComment, getBusinessLogicCallParameters, getBusinessLogicDeclParameters, getCSharpIdentifier, getCSharpStatusCode, getCSharpType, getCSharpTypeForIntrinsic, getCSharpTypeForScalar, getControllerReturnStatement, getFreePort, getHttpDeclParameters, getImports, getModelAttributes, getModelDeclarationName, getModelInstantiationName, getOpenApiConfig, getOperationVerbDecorator, getStatusCode, isEmptyResponseModel, isRecord, isStringEnumType, isValueType, resolveReferenceFromScopes, } from "./utils.js";
18
- export async function $onEmit(context) {
19
- let _unionCounter = 0;
20
- const controllers = new Map();
21
- const NoResourceContext = "RPCOperations";
22
- const doNotEmit = context.program.compilerOptions.dryRun || false;
23
- CSharpServiceOptions.getInstance().initialize(context.options);
24
- function getFileWriter(program) {
25
- return async (path) => !!(await program.host.stat(resolvePath(path)).catch((_) => false));
26
- }
27
- class CSharpCodeEmitter extends CodeTypeEmitter {
28
- #metadateMap = new Map();
29
- #generatedFileHeaderWithNullable = GeneratedFileHeaderWithNullable;
30
- #generatedFileHeader = GeneratedFileHeader;
31
- #sourceTypeKey = "sourceType";
32
- #nsKey = "ResolvedNamespace";
33
- #namespaces = new Map();
34
- #emitterOutputType = context.options["output-type"];
35
- #emitMocks = context.options["emit-mocks"];
36
- #useSwagger = context.options["use-swaggerui"] || false;
37
- #openapiPath = context.options["openapi-path"] || "openapi/openapi.yaml";
38
- #mockRegistrations = new Map();
39
- #opHelpers = new CSharpOperationHelpers(this.emitter);
40
- #fileExists = getFileWriter(this.emitter.getProgram());
41
- #getOrAddNamespaceForType(type) {
42
- const program = this.emitter.getProgram();
43
- switch (type.kind) {
44
- case "Boolean":
45
- case "String":
46
- case "StringTemplate":
47
- case "Number":
48
- case "Scalar":
49
- case "Intrinsic":
50
- case "FunctionParameter":
51
- case "ScalarConstructor":
52
- case "StringTemplateSpan":
53
- case "TemplateParameter":
54
- case "Tuple":
55
- case "FunctionType":
56
- return undefined;
57
- case "EnumMember":
58
- return this.#getOrAddNamespaceForType(type.enum);
59
- case "ModelProperty":
60
- case "UnionVariant":
61
- return this.#getOrAddNamespaceForType(type.type);
62
- case "Model":
63
- if (isRecord(type) && type.indexer)
64
- return this.#getOrAddNamespaceForType(type.indexer.value);
65
- if (type.indexer !== undefined && isNumericType(program, type.indexer?.key))
66
- return this.#getOrAddNamespaceForType(type.indexer.value);
67
- return this.#getOrAddNamespace(type.namespace);
68
- case "Union":
69
- if (isStringEnumType(program, type))
70
- return this.#getOrAddNamespace(type.namespace);
71
- const unionType = this.#coalesceTsUnion(type);
72
- if (unionType === undefined)
73
- return undefined;
74
- return this.#getOrAddNamespaceForType(unionType);
75
- default:
76
- return this.#getOrAddNamespace(type.namespace);
77
- }
78
- }
79
- #coalesceTsUnion(union) {
80
- let result = undefined;
81
- for (const [_, variant] of union.variants) {
82
- if (!isNullType(variant.type)) {
83
- if (result !== undefined && result !== variant.type)
84
- return undefined;
85
- result = variant.type;
86
- }
87
- }
88
- return result;
89
- }
90
- #getOrAddNamespace(typespecNamespace) {
91
- if (!typespecNamespace?.name)
92
- return this.#getDefaultNamespace();
93
- let resolvedNamespace = this.#namespaces.get(typespecNamespace);
94
- if (resolvedNamespace !== undefined)
95
- return resolvedNamespace;
96
- const nsName = getNamespaceFullName(typespecNamespace);
97
- resolvedNamespace = ensureCSharpIdentifier(this.emitter.getProgram(), typespecNamespace, nsName, NameCasingType.Namespace);
98
- this.#namespaces.set(typespecNamespace, resolvedNamespace);
99
- return resolvedNamespace;
100
- }
101
- #getDefaultNamespace() {
102
- return "TypeSpec.Service";
103
- }
104
- arrayDeclarationContext(array, name, elementType) {
105
- const arrayName = ensureCSharpIdentifier(this.emitter.getProgram(), array, name);
106
- const arrayFile = this.emitter.createSourceFile(`generated/models/${arrayName}.cs`);
107
- arrayFile.meta[this.#sourceTypeKey] = CSharpSourceType.Model;
108
- arrayFile.meta["skipEmit"] = true;
109
- const arrayNamespace = this.#getOrAddNamespace(array.namespace);
110
- return this.#createModelContext(arrayNamespace, arrayFile, arrayName);
111
- }
112
- arrayDeclaration(array, name, elementType) {
113
- return this.collectionDeclaration(elementType, array);
114
- }
115
- arrayLiteral(array, elementType) {
116
- this.emitter.emitType(elementType, this.emitter.getContext());
117
- const csType = getCSharpType(this.emitter.getProgram(), array, this.#getOrAddNamespaceForType(elementType));
118
- if (csType?.type) {
119
- return code `${csType.type.getTypeReference(this.emitter.getContext()?.scope)}`;
120
- }
121
- return this.collectionDeclaration(elementType, array);
122
- }
123
- collectionDeclaration(elementType, array) {
124
- const isUniqueItems = getUniqueItems(this.emitter.getProgram(), array);
125
- const collectionType = isUniqueItems
126
- ? CollectionType.ISet
127
- : CSharpServiceOptions.getInstance().collectionType;
128
- switch (collectionType) {
129
- case CollectionType.ISet:
130
- return code `ISet<${this.emitter.emitTypeReference(elementType, this.emitter.getContext())}>`;
131
- case CollectionType.IEnumerable:
132
- return code `IEnumerable<${this.emitter.emitTypeReference(elementType, this.emitter.getContext())}>`;
133
- case CollectionType.Array:
134
- default:
135
- return code `${this.emitter.emitTypeReference(elementType, this.emitter.getContext())}[]`;
136
- }
137
- }
138
- booleanLiteral(boolean) {
139
- return code `${boolean.value === true ? "true" : "false"}`;
140
- }
141
- unionLiteral(union) {
142
- const csType = coalesceUnionTypes(this.emitter.getProgram(), union);
143
- return this.emitter.result.rawCode(csType ? csType.getTypeReference(this.emitter.getContext()?.scope) : "object");
144
- }
145
- declarationName(declarationType) {
146
- switch (declarationType.kind) {
147
- case "Enum":
148
- if (!declarationType.name)
149
- return `Enum${_unionCounter++}`;
150
- return getCSharpIdentifier(declarationType.name, NameCasingType.Class);
151
- case "Interface":
152
- if (!declarationType.name)
153
- return `Interface${_unionCounter++}`;
154
- return getCSharpIdentifier(declarationType.name, NameCasingType.Class);
155
- case "Model":
156
- if (!declarationType.name)
157
- return getModelDeclarationName(this.emitter.getProgram(), declarationType, `${_unionCounter++}`);
158
- return getCSharpIdentifier(declarationType.name, NameCasingType.Class);
159
- case "Operation":
160
- return getCSharpIdentifier(declarationType.name, NameCasingType.Class);
161
- case "Union":
162
- if (!declarationType.name)
163
- return `Union${_unionCounter++}`;
164
- return getCSharpIdentifier(declarationType.name, NameCasingType.Class);
165
- case "Scalar":
166
- default:
167
- return getCSharpIdentifier(declarationType.name, NameCasingType.Variable);
168
- }
169
- }
170
- enumDeclaration(en, name) {
171
- if (getEnumType(en) === "double")
172
- return "";
173
- const program = this.emitter.getProgram();
174
- const enumName = ensureCSharpIdentifier(program, en, name);
175
- const namespace = this.emitter.getContext().namespace;
176
- const doc = getDoc(this.emitter.getProgram(), en);
177
- const attributes = getModelAttributes(program, en, enumName);
178
- this.#metadateMap.set(en, new CSharpType({ name: enumName, namespace: namespace }));
179
- return this.emitter.result.declaration(enumName, code `
180
- namespace ${namespace}
181
- {
182
-
183
- ${doc ? `${formatComment(doc)}` : ""}
184
- ${attributes.map((attribute) => attribute.getApplicationString(this.emitter.getContext().scope)).join("\n")}
185
- public enum ${enumName}
186
- {
187
- ${this.emitter.emitEnumMembers(en)}
188
- }
189
- } `);
190
- }
191
- enumDeclarationContext(en) {
192
- if (getEnumType(en) === "double")
193
- return this.emitter.getContext();
194
- const enumName = ensureCSharpIdentifier(this.emitter.getProgram(), en, en.name);
195
- const enumFile = this.emitter.createSourceFile(`generated/models/${enumName}.cs`);
196
- enumFile.meta[this.#sourceTypeKey] = CSharpSourceType.Model;
197
- const enumNamespace = this.#getOrAddNamespace(en.namespace);
198
- return this.#createEnumContext(enumNamespace, enumFile, enumName);
199
- }
200
- enumMembers(en) {
201
- const enumType = getEnumType(en);
202
- const result = new StringBuilder();
203
- let i = 0;
204
- for (const [name, member] of en.members) {
205
- i++;
206
- const memberName = ensureCSharpIdentifier(this.emitter.getProgram(), member, name);
207
- this.#metadateMap.set(member, { name: memberName });
208
- if (enumType === "string") {
209
- result.push(code `
210
- [JsonStringEnumMemberName("${member.value ? member.value : name}")]
211
- ${ensureCSharpIdentifier(this.emitter.getProgram(), member, name)}`);
212
- if (i < en.members.size)
213
- result.pushLiteralSegment(",\n");
214
- }
215
- else if (member.value !== undefined) {
216
- result.push(code `
217
- ${ensureCSharpIdentifier(this.emitter.getProgram(), member, name)} = ${member.value.toString()}`);
218
- if (i < en.members.size)
219
- result.pushLiteralSegment(",\n");
220
- }
221
- }
222
- return this.emitter.result.rawCode(result.reduce());
223
- }
224
- intrinsic(intrinsic, name) {
225
- switch (intrinsic.name) {
226
- case "unknown":
227
- case "null":
228
- return this.emitter.result.rawCode(code `${UnknownType.getTypeReference(this.emitter.getContext().scope)}`);
229
- case "ErrorType":
230
- case "never":
231
- reportDiagnostic(this.emitter.getProgram(), {
232
- code: "invalid-intrinsic",
233
- target: intrinsic,
234
- format: { typeName: intrinsic.name },
235
- });
236
- return "";
237
- case "void":
238
- const type = getCSharpTypeForIntrinsic(this.emitter.getProgram(), intrinsic);
239
- return this.emitter.result.rawCode(`${type?.type.getTypeReference(this.emitter.getContext().scope)}`);
240
- }
241
- }
242
- #emitUsings(file) {
243
- const builder = new StringBuilder();
244
- if (file === undefined) {
245
- file = this.emitter.getContext().file;
246
- }
247
- for (const ns of [...file.imports.keys()])
248
- builder.pushLiteralSegment(`using ${ns};`);
249
- return builder.segments.join("\n");
250
- }
251
- modelDeclaration(model, name) {
252
- const parts = this.#getMultipartParts(model);
253
- if (parts.length > 0) {
254
- parts.forEach((p) => this.emitter.emitType(p));
255
- return "";
256
- }
257
- const isErrorType = isErrorModel(this.emitter.getProgram(), model);
258
- if (model.baseModel && model.baseModel.namespace !== model.namespace) {
259
- const resolvedNs = this.#getOrAddNamespaceForType(model.baseModel);
260
- if (resolvedNs)
261
- checkOrAddNamespaceToScope(resolvedNs, this.emitter.getContext().scope);
262
- }
263
- const baseModelRef = model.baseModel
264
- ? code `: ${this.emitter.emitTypeReference(model.baseModel, this.emitter.getContext())}`
265
- : "";
266
- const baseClass = baseModelRef || (isErrorType ? ": HttpServiceException" : "");
267
- const namespace = this.emitter.getContext().namespace;
268
- const className = ensureCSharpIdentifier(this.emitter.getProgram(), model, name);
269
- const doc = getDoc(this.emitter.getProgram(), model);
270
- const attributes = getModelAttributes(this.emitter.getProgram(), model, className);
271
- const exceptionConstructor = isErrorType
272
- ? this.getModelExceptionConstructor(this.emitter.getProgram(), model, name, className)
273
- : "";
274
- this.#metadateMap.set(model, new CSharpType({ name: className, namespace: namespace }));
275
- const decl = this.emitter.result.declaration(className, code `
276
- namespace ${namespace} {
277
-
278
- ${doc ? `${formatComment(doc)}\n` : ""}${`${attributes.map((attribute) => attribute.getApplicationString(this.emitter.getContext().scope)).join("\n")}${attributes?.length > 0 ? "\n" : ""}`}public partial class ${className} ${baseClass} {
279
- ${exceptionConstructor ? `${exceptionConstructor}\n` : ""}${this.emitter.emitModelProperties(model)}
280
- }
281
- } `);
282
- return decl;
283
- }
284
- getModelExceptionConstructor(program, model, modelName, className) {
285
- if (!isErrorModel(program, model))
286
- return undefined;
287
- const constructor = this.getExceptionConstructorData(program, model, modelName);
288
- const isParent = !!model.derivedModels?.length;
289
- return `public ${className}(${constructor.properties}) : base(${constructor.statusCode?.value ?? `400`}${constructor.header ? `, \n\t\t headers: new(){${constructor.header}}` : ""}${constructor.value ? `, \n\t\t value: new{${constructor.value}}` : ""})
290
- { ${constructor.body ? `\n${constructor.body}` : ""}\n\t}${isParent ? `\npublic ${className}(int statusCode, object? value = null, Dictionary<string, string>? headers = default): base(statusCode, value, headers) {}\n` : ""}`;
291
- }
292
- isDuplicateExceptionName(name) {
293
- const exceptionPropertyNames = [
294
- "value",
295
- "headers",
296
- "stacktrace",
297
- "source",
298
- "message",
299
- "innerexception",
300
- "hresult",
301
- "data",
302
- "targetsite",
303
- "helplink",
304
- ];
305
- return exceptionPropertyNames.includes(name.toLowerCase());
306
- }
307
- getExceptionConstructorData(program, model, modelName) {
308
- const allProperties = new ModelInfo().getAllProperties(program, model) ?? [];
309
- const propertiesWithDefaults = allProperties.map((prop) => {
310
- const { defaultValue: typeDefault } = this.#findPropertyType(prop);
311
- const defaultValue = prop.defaultValue
312
- ? code `${JSON.stringify(serializeValueAsJson(program, prop.defaultValue, prop))}`
313
- : typeDefault;
314
- return { prop, defaultValue };
315
- });
316
- const sortedProperties = propertiesWithDefaults
317
- .filter(({ prop }) => !isStatusCode(program, prop))
318
- .sort(({ prop: a, defaultValue: aDefault }, { prop: b, defaultValue: bDefault }) => {
319
- if (!a.optional && !aDefault && (b.optional || bDefault))
320
- return -1;
321
- if (!b.optional && !bDefault && (a.optional || aDefault))
322
- return 1;
323
- return 0;
324
- });
325
- const properties = [];
326
- const body = [];
327
- const header = [];
328
- const value = [];
329
- const statusCode = getStatusCode(program, model);
330
- if (statusCode?.requiresConstructorArgument) {
331
- properties.push(`int ${statusCode.value}`);
332
- }
333
- for (const { prop, defaultValue } of sortedProperties) {
334
- let propertyName = ensureCSharpIdentifier(program, prop, prop.name);
335
- if (modelName === propertyName || this.isDuplicateExceptionName(propertyName)) {
336
- propertyName = `${propertyName}Prop`;
337
- }
338
- const type = getCSharpType(program, prop.type);
339
- properties.push(`${type?.type.name} ${prop.name}${defaultValue ? ` = ${defaultValue}` : `${prop.optional ? " = default" : ""}`}`);
340
- body.push(`\t\t${propertyName} = ${prop.name};`);
341
- if (isHeader(program, prop)) {
342
- const headerName = getHeaderFieldName(program, prop);
343
- header.push(`{"${headerName}", ${prop.name}}`);
344
- }
345
- else {
346
- value.push(`${prop.name} = ${prop.name}`);
347
- }
348
- }
349
- return {
350
- properties: properties.join(", "),
351
- body: body.join("\n"),
352
- header: header.join(", "),
353
- value: value.join(","),
354
- statusCode: statusCode,
355
- };
356
- }
357
- modelDeclarationContext(model, name) {
358
- function getSourceModels(source, visited = new Set()) {
359
- const result = [];
360
- if (visited.has(source))
361
- return [];
362
- result.push(source);
363
- visited.add(source);
364
- for (const candidate of source.sourceModels) {
365
- result.push(...getSourceModels(candidate.model, visited));
366
- }
367
- return result;
368
- }
369
- function getModelNamespace(model) {
370
- const sourceModels = getSourceModels(model);
371
- if (sourceModels.length === 0)
372
- return undefined;
373
- return sourceModels
374
- .filter((m) => m.namespace !== undefined)
375
- .flatMap((s) => s.namespace)
376
- .reduce((c, n) => (c === n ? c : undefined));
377
- }
378
- if (this.#isMultipartModel(model))
379
- return this.emitter.getContext();
380
- const modelName = ensureCSharpIdentifier(this.emitter.getProgram(), model, name);
381
- const modelFile = this.emitter.createSourceFile(`generated/models/${modelName}.cs`);
382
- modelFile.meta[this.#sourceTypeKey] = CSharpSourceType.Model;
383
- const ns = model.namespace ?? getModelNamespace(model);
384
- const modelNamespace = this.#getOrAddNamespace(ns);
385
- return this.#createModelContext(modelNamespace, modelFile, modelName);
386
- }
387
- modelInstantiationContext(model) {
388
- if (this.#isMultipartModel(model))
389
- return this.emitter.getContext();
390
- const modelName = getModelInstantiationName(this.emitter.getProgram(), model, model.name);
391
- const sourceFile = this.emitter.createSourceFile(`generated/models/${modelName}.cs`);
392
- sourceFile.meta[this.#sourceTypeKey] = CSharpSourceType.Model;
393
- const modelNamespace = this.#getOrAddNamespace(model.namespace);
394
- const context = this.#createModelContext(modelNamespace, sourceFile, model.name);
395
- context.instantiationName = modelName;
396
- return context;
397
- }
398
- modelInstantiation(model, name) {
399
- const parts = this.#getMultipartParts(model);
400
- if (parts.length > 0) {
401
- parts.forEach((p) => this.emitter.emitType(p));
402
- return "";
403
- }
404
- const program = this.emitter.getProgram();
405
- const recordType = getRecordType(program, model);
406
- if (recordType !== undefined) {
407
- const valueType = this.#getSimpleType(recordType);
408
- return code `Dictionary<string, ${valueType ? valueType?.getTypeReference() : this.emitter.emitTypeReference(recordType)}>`;
409
- }
410
- const context = this.emitter.getContext();
411
- const className = context.instantiationName ?? name;
412
- return this.modelDeclaration(model, className);
413
- }
414
- #getSimpleType(type) {
415
- switch (type.kind) {
416
- case "Model":
417
- if (!isRecord(type))
418
- return undefined;
419
- return getCSharpType(this.emitter.getProgram(), type)?.type;
420
- case "Boolean":
421
- case "Intrinsic":
422
- case "ModelProperty":
423
- case "Number":
424
- case "Scalar":
425
- case "String":
426
- case "StringTemplate":
427
- case "StringTemplateSpan":
428
- case "Tuple":
429
- return getCSharpType(this.emitter.getProgram(), type)?.type;
430
- default:
431
- return undefined;
432
- }
433
- }
434
- #getMultipartParts(model) {
435
- const parts = [...model.properties.values()]
436
- .flatMap((p) => getHttpPart(this.emitter.getProgram(), p.type)?.type)
437
- .filter((t) => t !== undefined);
438
- if (model.baseModel) {
439
- return parts.concat(this.#getMultipartParts(model.baseModel));
440
- }
441
- return parts;
442
- }
443
- #isMultipartModel(model) {
444
- const multipartTypes = this.#getMultipartParts(model);
445
- return multipartTypes.length > 0;
446
- }
447
- modelProperties(model) {
448
- const result = new StringBuilder();
449
- for (const [_, prop] of model.properties) {
450
- if (!isVoidType(prop.type) &&
451
- !isNeverType(prop.type) &&
452
- !isNullType(prop.type) &&
453
- !isErrorModel(this.emitter.getProgram(), prop.type)) {
454
- result.push(code `${this.emitter.emitModelProperty(prop)}`);
455
- }
456
- }
457
- return result.reduce();
458
- }
459
- modelLiteralContext(model) {
460
- const name = this.emitter.emitDeclarationName(model) || "";
461
- return this.modelDeclarationContext(model, name);
462
- }
463
- modelLiteral(model) {
464
- const modelName = this.emitter.getContext().name;
465
- reportDiagnostic(this.emitter.getProgram(), {
466
- code: "anonymous-model",
467
- target: model,
468
- format: { emittedName: modelName },
469
- });
470
- return this.modelDeclaration(model, modelName);
471
- }
472
- #isInheritedProperty(property) {
473
- const visited = [];
474
- function isInherited(model, propertyName) {
475
- if (visited.includes(model))
476
- return false;
477
- visited.push(model);
478
- if (model.properties.has(propertyName))
479
- return true;
480
- if (model.baseModel === undefined)
481
- return false;
482
- return isInherited(model.baseModel, propertyName);
483
- }
484
- const model = property.model;
485
- if (model === undefined || model.baseModel === undefined)
486
- return false;
487
- return isInherited(model.baseModel, property.name);
488
- }
489
- modelPropertyLiteral(property) {
490
- if (isStatusCode(this.emitter.getProgram(), property))
491
- return "";
492
- let propertyName = ensureCSharpIdentifier(this.emitter.getProgram(), property, property.name);
493
- const { typeReference: typeName, defaultValue: typeDefault, nullableType: nullable, } = this.#findPropertyType(property);
494
- const doc = getDoc(this.emitter.getProgram(), property);
495
- const attributes = new Map(getModelAttributes(this.emitter.getProgram(), property, propertyName).map((a) => [
496
- a.type.name,
497
- a,
498
- ]));
499
- const modelName = this.emitter.getContext()["name"];
500
- if (modelName === propertyName ||
501
- (this.isDuplicateExceptionName(propertyName) &&
502
- property.model &&
503
- isErrorModel(this.emitter.getProgram(), property.model))) {
504
- propertyName = `${propertyName}Prop`;
505
- const attr = getEncodedNameAttribute(this.emitter.getProgram(), property, propertyName);
506
- if (!attributes.has(attr.type.name))
507
- attributes.set(attr.type.name, attr);
508
- }
509
- const defaultValue = this.#opHelpers.getDefaultValue(this.emitter.getProgram(), property.type, property.defaultValue) ?? typeDefault;
510
- const attributeList = [...attributes.values()];
511
- return this.emitter.result
512
- .rawCode(code `${doc ? `${formatComment(doc)}\n` : ""}${`${attributeList.map((attribute) => attribute.getApplicationString(this.emitter.getContext().scope)).join("\n")}${attributeList?.length > 0 ? "\n" : ""}`}public ${this.#isInheritedProperty(property) ? "new " : ""}${typeName}${isValueType(this.emitter.getProgram(), property.type) && (property.optional || nullable)
513
- ? "?"
514
- : ""} ${propertyName} { get; ${typeDefault ? "}" : "set; }"}${defaultValue ? ` = ${defaultValue};\n` : "\n"}
515
- `);
516
- }
517
- #findPropertyType(property) {
518
- return this.#opHelpers.getTypeInfo(this.emitter.getProgram(), property.type, property);
519
- }
520
- #isMultipartRequest(operation) {
521
- const body = operation.parameters.body;
522
- if (body === undefined)
523
- return false;
524
- return body.bodyKind === "multipart";
525
- }
526
- #hasMultipartOperation(iface) {
527
- for (const [_, operation] of iface.operations) {
528
- const [httpOp, _] = getHttpOperation(this.emitter.getProgram(), operation);
529
- if (this.#isMultipartRequest(httpOp))
530
- return true;
531
- }
532
- return false;
533
- }
534
- modelPropertyReference(property) {
535
- return code `${this.emitter.emitTypeReference(property.type)}`;
536
- }
537
- numericLiteral(number) {
538
- return this.emitter.result.rawCode(code `${number.value.toString()}`);
539
- }
540
- interfaceDeclaration(iface, name) {
541
- // interface declaration
542
- const ifaceName = `I${ensureCSharpIdentifier(this.emitter.getProgram(), iface, name, NameCasingType.Class)}`;
543
- const namespace = this.emitter.getContext().namespace;
544
- const doc = getDoc(this.emitter.getProgram(), iface);
545
- const attributes = getModelAttributes(this.emitter.getProgram(), iface, ifaceName);
546
- this.#metadateMap.set(iface, new CSharpType({ name: ifaceName, namespace: namespace }));
547
- const decl = this.emitter.result.declaration(ifaceName, code `
548
- namespace ${namespace} {
549
-
550
- ${doc ? `${formatComment(doc)}\n` : ""}${`${attributes.map((attribute) => attribute.getApplicationString(this.emitter.getContext().scope)).join("\n")}${attributes?.length > 0 ? "\n" : ""}`}public interface ${ifaceName} {
551
- ${this.emitter.emitInterfaceOperations(iface)}
552
- }
553
- } `);
554
- return decl;
555
- }
556
- interfaceDeclarationContext(iface, name) {
557
- // set up interfaces file for declaration
558
- const ifaceName = `I${ensureCSharpIdentifier(this.emitter.getProgram(), iface, name, NameCasingType.Class)}`;
559
- const sourceFile = this.emitter.createSourceFile(`generated/operations/${ifaceName}.cs`);
560
- sourceFile.meta[this.#sourceTypeKey] = CSharpSourceType.Interface;
561
- sourceFile.meta["nullable"] = true;
562
- const ifaceNamespace = this.#getOrAddNamespace(iface.namespace);
563
- sourceFile.imports.set("System", ["System"]);
564
- sourceFile.imports.set("System.Net", ["System.Net"]);
565
- sourceFile.imports.set("System.Text.Json", ["System.Text.Json"]);
566
- sourceFile.imports.set("System.Text.Json.Serialization", ["System.Text.Json.Serialization"]);
567
- sourceFile.imports.set("System.Threading.Tasks", ["System.Threading.Tasks"]);
568
- sourceFile.imports.set("Microsoft.AspNetCore.Mvc", ["Microsoft.AspNetCore.Mvc"]);
569
- if (this.#hasMultipartOperation(iface)) {
570
- sourceFile.imports.set("Microsoft.AspNetCore.WebUtilities", [
571
- "Microsoft.AspNetCore.WebUtilities",
572
- ]);
573
- }
574
- return this.#createModelContext(ifaceNamespace, sourceFile, ifaceName);
575
- }
576
- interfaceDeclarationOperations(iface) {
577
- // add in operations
578
- const builder = new StringBuilder();
579
- const context = this.emitter.getContext();
580
- const name = `${ensureCSharpIdentifier(this.emitter.getProgram(), iface, iface.name, NameCasingType.Class)}`;
581
- const ifaceNamespace = this.#getOrAddNamespace(iface.namespace);
582
- const namespace = ifaceNamespace;
583
- const mock = {
584
- className: name,
585
- interfaceName: `I${name}`,
586
- methods: [],
587
- namespace: namespace,
588
- usings: [],
589
- };
590
- for (const [name, operation] of iface.operations) {
591
- if (isTemplateDeclaration(operation))
592
- continue;
593
- const doc = getDoc(this.emitter.getProgram(), operation);
594
- const returnTypes = [];
595
- const [httpOp, _] = getHttpOperation(this.emitter.getProgram(), operation);
596
- for (const response of httpOp.responses.filter((r) => !isErrorModel(this.emitter.getProgram(), r.type))) {
597
- const [_, responseType] = this.#resolveOperationResponse(response, httpOp.operation);
598
- returnTypes.push(responseType);
599
- }
600
- const returnInfo = coalesceTypes(this.emitter.getProgram(), returnTypes, namespace);
601
- const returnType = returnInfo?.type || UnknownType;
602
- const opName = ensureCSharpIdentifier(this.emitter.getProgram(), operation, name, NameCasingType.Method);
603
- const parameters = this.#opHelpers.getParameters(this.emitter.getProgram(), httpOp);
604
- const opImpl = {
605
- methodName: `${opName}Async`,
606
- methodParams: `${getBusinessLogicDeclParameters(parameters)}`,
607
- returnType: returnType,
608
- returnTypeName: `${returnType.name === "void" ? "Task" : `Task<${returnType.getTypeReference(context.scope)}>`}`,
609
- instantiatedReturnType: returnType.name === "void"
610
- ? undefined
611
- : `${returnType.getTypeReference(context.scope)}`,
612
- };
613
- const opDecl = this.emitter.result.declaration(opName, code `${doc ? `${formatComment(doc)}\n` : ""}${opImpl.returnTypeName} ${opImpl.methodName}( ${opImpl.methodParams});`);
614
- mock.methods.push(opImpl);
615
- builder.push(code `${opDecl.value}\n`);
616
- this.emitter.emitInterfaceOperation(operation);
617
- }
618
- mock.usings.push(...getImports(context.scope));
619
- this.#mockRegistrations.set(mock.interfaceName, mock);
620
- return builder.reduce();
621
- }
622
- interfaceOperationDeclarationContext(operation) {
623
- const resource = getResourceOperation(this.emitter.getProgram(), operation);
624
- const controllerName = operation.interface !== undefined
625
- ? operation.interface.name
626
- : resource === undefined
627
- ? NoResourceContext
628
- : resource.resourceType.name;
629
- return this.#createOrGetResourceContext(controllerName, operation, resource?.resourceType);
630
- }
631
- interfaceOperationDeclaration(operation, name) {
632
- const operationName = ensureCSharpIdentifier(this.emitter.getProgram(), operation, name, NameCasingType.Method);
633
- const doc = getDoc(this.emitter.getProgram(), operation);
634
- const [httpOperation, _] = getHttpOperation(this.emitter.getProgram(), operation);
635
- const multipart = this.#isMultipartRequest(httpOperation);
636
- const parameters = this.#opHelpers.getParameters(this.emitter.getProgram(), httpOperation);
637
- const declParams = getHttpDeclParameters(parameters);
638
- if (multipart) {
639
- const context = this.emitter.getContext();
640
- context.file.imports.set("Microsoft.AspNetCore.WebUtilities", [
641
- "Microsoft.AspNetCore.WebUtilities",
642
- ]);
643
- context.file.imports.set("Microsoft.AspNetCore.Http.Extensions", [
644
- "Microsoft.AspNetCore.Http.Extensions",
645
- ]);
646
- }
647
- const responseInfo = this.#getOperationResponse(httpOperation);
648
- const status = responseInfo?.statusCode ?? 200;
649
- const response = responseInfo?.resultType ??
650
- new CSharpType({
651
- name: "void",
652
- namespace: "System",
653
- isBuiltIn: true,
654
- isValueType: false,
655
- });
656
- const hasResponseValue = response.name !== "void";
657
- const returnStatement = getControllerReturnStatement(status, hasResponseValue);
658
- if (!this.#isMultipartRequest(httpOperation)) {
659
- return this.emitter.result.declaration(operation.name, code `
660
- ${doc ? `${formatComment(doc)}` : ""}
661
- [${getOperationVerbDecorator(httpOperation)}]
662
- [Route("${httpOperation.path}")]
663
- ${this.emitter.emitOperationReturnType(operation)}
664
- public virtual async Task<IActionResult> ${operationName}(${declParams})
665
- {
666
- ${hasResponseValue
667
- ? `var result = await ${this.emitter.getContext().resourceName}Impl.${operationName}Async(${getBusinessLogicCallParameters(parameters)});
668
- ${returnStatement}`
669
- : `await ${this.emitter.getContext().resourceName}Impl.${operationName}Async(${getBusinessLogicCallParameters(parameters)});
670
- ${returnStatement}`}
671
- }`);
672
- }
673
- else {
674
- return this.emitter.result.declaration(operation.name, code `
675
- ${doc ? `${formatComment(doc)}` : ""}
676
- [${getOperationVerbDecorator(httpOperation)}]
677
- [Route("${httpOperation.path}")]
678
- [Consumes("multipart/form-data")]
679
- ${this.emitter.emitOperationReturnType(operation)}
680
- public virtual async Task<IActionResult> ${operationName}(${declParams})
681
- {
682
- var boundary = Request.GetMultipartBoundary();
683
- if (boundary == null)
684
- {
685
- return BadRequest("Request missing multipart boundary");
686
- }
687
-
688
-
689
- var reader = new MultipartReader(boundary, Request.Body);
690
- ${hasResponseValue
691
- ? `var result = await ${this.emitter.getContext().resourceName}Impl.${operationName}Async(${getBusinessLogicCallParameters(parameters)});
692
- ${returnStatement}`
693
- : `await ${this.emitter.getContext().resourceName}Impl.${operationName}Async(${getBusinessLogicCallParameters(parameters)});
694
- ${returnStatement}`}
695
- }`);
696
- }
697
- }
698
- operationDeclarationContext(operation, name) {
699
- const resource = getResourceOperation(this.emitter.getProgram(), operation);
700
- const controllerName = (operation.interface?.name ?? resource === undefined)
701
- ? NoResourceContext
702
- : resource.resourceType.name;
703
- return this.#createOrGetResourceContext(controllerName, operation, resource?.resourceType);
704
- }
705
- operationDeclaration(operation, name) {
706
- const operationName = ensureCSharpIdentifier(this.emitter.getProgram(), operation, name, NameCasingType.Method);
707
- const doc = getDoc(this.emitter.getProgram(), operation);
708
- const [httpOperation, _] = getHttpOperation(this.emitter.getProgram(), operation);
709
- const parameters = this.#opHelpers.getParameters(this.emitter.getProgram(), httpOperation);
710
- const declParams = getHttpDeclParameters(parameters);
711
- const responseInfo = this.#getOperationResponse(httpOperation);
712
- const status = responseInfo?.statusCode ?? 200;
713
- const response = responseInfo?.resultType ??
714
- new CSharpType({
715
- name: "void",
716
- namespace: "System",
717
- isBuiltIn: true,
718
- isValueType: false,
719
- });
720
- const hasResponseValue = response.name !== "void";
721
- const returnStatement = getControllerReturnStatement(status, hasResponseValue);
722
- return this.emitter.result.declaration(operation.name, code `
723
- ${doc ? `${formatComment(doc)}` : ""}
724
- [${getOperationVerbDecorator(httpOperation)}]
725
- [Route("${httpOperation.path}")]
726
- ${this.emitter.emitOperationReturnType(operation)}
727
- public virtual async Task<IActionResult> ${operationName}(${declParams})
728
- {
729
- ${hasResponseValue
730
- ? `var result = await ${this.emitter.getContext().resourceName}Impl.${operationName}Async(${getBusinessLogicCallParameters(parameters)});
731
- ${returnStatement}`
732
- : `await ${this.emitter.getContext().resourceName}Impl.${operationName}Async(${getBusinessLogicCallParameters(parameters)});
733
- ${returnStatement}`}
734
- }`);
735
- }
736
- operationReturnType(operation, returnType) {
737
- const [httpOperation, _] = getHttpOperation(this.emitter.getProgram(), operation);
738
- return this.#emitOperationResponses(httpOperation);
739
- }
740
- stringTemplate(stringTemplate) {
741
- return this.emitter.result.rawCode(stringTemplate.stringValue || "");
742
- }
743
- #resolveOperationResponse(response, operation) {
744
- function getName(sourceType, part) {
745
- return ensureCSharpIdentifier(emitter.getProgram(), sourceType, part, NameCasingType.Class);
746
- }
747
- let responseType = new HttpMetadata().resolveLogicalResponseType(this.emitter.getProgram(), response);
748
- if (responseType.kind === "Model" && !responseType.name) {
749
- const modelName = `${getName(responseType, operation.interface.name)}${getName(responseType, operation.name)}Response}`;
750
- const returnedType = this.emitter
751
- .getProgram()
752
- .checker.cloneType(responseType, { name: modelName });
753
- responseType = returnedType;
754
- }
755
- // TemplateParameter types cannot be emitted (they are unresolved template placeholders).
756
- // Template operations are filtered in interfaceDeclarationOperations, but this guard
757
- // prevents crashes if a TemplateParameter response type is encountered via other paths.
758
- if (responseType.kind !== "TemplateParameter") {
759
- this.emitter.emitType(responseType);
760
- }
761
- const context = this.emitter.getContext();
762
- const result = getCSharpType(this.emitter.getProgram(), responseType, context.namespace);
763
- return [result?.type || UnknownType, responseType];
764
- }
765
- #getOperationResponse(operation) {
766
- const validResponses = operation.responses.filter((r) => !isErrorModel(this.emitter.getProgram(), r.type) &&
767
- getCSharpStatusCode(r.statusCodes) !== undefined);
768
- if (validResponses.length < 1)
769
- return undefined;
770
- const response = validResponses[0];
771
- const csharpStatusCode = getCSharpStatusCode(response.statusCodes);
772
- if (csharpStatusCode === undefined)
773
- return undefined;
774
- const responseType = new HttpMetadata().resolveLogicalResponseType(this.emitter.getProgram(), response);
775
- const context = this.emitter.getContext();
776
- const result = getCSharpType(this.emitter.getProgram(), responseType, context.namespace);
777
- const resultType = result?.type || UnknownType;
778
- return {
779
- csharpStatusCode,
780
- resultType,
781
- statusCode: response.statusCodes,
782
- };
783
- }
784
- #emitOperationResponses(operation) {
785
- function isValid(program, response) {
786
- return (!isErrorModel(program, response.type) &&
787
- getCSharpStatusCode(response.statusCodes) !== undefined);
788
- }
789
- const builder = new StringBuilder();
790
- for (const response of operation.responses) {
791
- const [responseType, _] = this.#resolveOperationResponse(response, operation.operation);
792
- if (isValid(this.emitter.getProgram(), response)) {
793
- builder.push(code `${builder.segments.length > 0 ? "\n" : ""}${this.#emitOperationResponseDecorator(response, responseType)}`);
794
- }
795
- }
796
- return builder.reduce();
797
- }
798
- #emitOperationResponseDecorator(response, result) {
799
- return this.emitter.result.rawCode(code `[ProducesResponseType((int)${getCSharpStatusCode(response.statusCodes)}, Type = typeof(${this.#emitResponseType(result)}))]`);
800
- }
801
- #emitResponseType(type) {
802
- const context = this.emitter.getContext();
803
- return type.getTypeReference(context.scope);
804
- }
805
- unionDeclaration(union, name) {
806
- const baseType = coalesceUnionTypes(this.emitter.getProgram(), union);
807
- if (isStringEnumType(this.emitter.getProgram(), union)) {
808
- const program = this.emitter.getProgram();
809
- const unionName = ensureCSharpIdentifier(program, union, name);
810
- const namespace = this.emitter.getContext().namespace;
811
- const doc = getDoc(this.emitter.getProgram(), union);
812
- const attributes = getModelAttributes(program, union, unionName);
813
- this.#metadateMap.set(union, new CSharpType({ name: unionName, namespace: namespace }));
814
- return this.emitter.result.declaration(unionName, code `
815
- namespace ${namespace}
816
- {
817
-
818
- ${doc ? `${formatComment(doc)}` : ""}
819
- ${attributes.map((attribute) => attribute.getApplicationString(this.emitter.getContext().scope)).join("\n")}
820
- public enum ${unionName}
821
- {
822
- ${this.emitter.emitUnionVariants(union)}
823
- }
824
- } `);
825
- }
826
- return this.emitter.result.rawCode(code `${baseType.getTypeReference(this.emitter.getContext().scope)}`);
827
- }
828
- unionDeclarationContext(union) {
829
- if (isStringEnumType(this.emitter.getProgram(), union)) {
830
- const unionName = ensureCSharpIdentifier(this.emitter.getProgram(), union, union.name || "Union");
831
- const unionFile = this.emitter.createSourceFile(`generated/models/${unionName}.cs`);
832
- unionFile.meta[this.#sourceTypeKey] = CSharpSourceType.Model;
833
- const unionNamespace = this.#getOrAddNamespace(union.namespace);
834
- return this.#createEnumContext(unionNamespace, unionFile, unionName);
835
- }
836
- else {
837
- return this.emitter.getContext();
838
- }
839
- }
840
- unionInstantiation(union, name) {
841
- return super.unionInstantiation(union, name);
842
- }
843
- unionInstantiationContext(union, name) {
844
- return super.unionInstantiationContext(union, name);
845
- }
846
- unionVariants(union) {
847
- const result = new StringBuilder();
848
- let i = 0;
849
- for (const [name, variant] of union.variants) {
850
- i++;
851
- if (variant.type.kind === "String") {
852
- const nameHint = name || variant.type.value;
853
- const memberName = ensureCSharpIdentifier(this.emitter.getProgram(), variant, nameHint);
854
- this.#metadateMap.set(variant, { name: memberName });
855
- result.push(code `
856
- [JsonStringEnumMemberName("${variant.type.value}")]
857
- ${ensureCSharpIdentifier(this.emitter.getProgram(), variant, nameHint, NameCasingType.Property)}`);
858
- if (i < union.variants.size)
859
- result.pushLiteralSegment(", ");
860
- }
861
- }
862
- return this.emitter.result.rawCode(result.reduce());
863
- }
864
- unionVariantContext(union) {
865
- return super.unionVariantContext(union);
866
- }
867
- #createModelContext(namespace, file, name) {
868
- file.imports.set("System", ["System"]);
869
- file.imports.set("System.Text.Json", ["System.Text.Json"]);
870
- file.imports.set("System.Text.Json.Serialization", ["System.Text.Json.Serialization"]);
871
- file.imports.set("TypeSpec.Helpers.JsonConverters", ["TypeSpec.Helpers.JsonConverters"]);
872
- file.imports.set("TypeSpec.Helpers", ["TypeSpec.Helpers"]);
873
- file.meta[this.#nsKey] = namespace;
874
- const context = {
875
- namespace: namespace,
876
- name: name,
877
- file: file,
878
- scope: file.globalScope,
879
- };
880
- return context;
881
- }
882
- #createEnumContext(namespace, file, name) {
883
- file.imports.set("System.Text.Json", ["System.Text.Json"]);
884
- file.imports.set("System.Text.Json.Serialization", ["System.Text.Json.Serialization"]);
885
- file.meta[this.#nsKey] = namespace;
886
- return {
887
- namespace: namespace,
888
- name: name,
889
- file: file,
890
- scope: file.globalScope,
891
- };
892
- }
893
- #createOrGetResourceContext(name, operation, resource) {
894
- name = ensureCSharpIdentifier(this.emitter.getProgram(), operation, name, NameCasingType.Class);
895
- const namespace = this.#getOrAddNamespace(operation.namespace);
896
- let context = controllers.get(`${namespace}.${name}`);
897
- if (context !== undefined)
898
- return context;
899
- const sourceFile = this.emitter.createSourceFile(`generated/controllers/${name}Controller.cs`);
900
- sourceFile.meta[this.#sourceTypeKey] = CSharpSourceType.Controller;
901
- sourceFile.meta["resourceName"] = name;
902
- sourceFile.meta["resource"] = `${name}Controller`;
903
- sourceFile.meta["namespace"] = namespace;
904
- sourceFile.imports.set("System", ["System"]);
905
- sourceFile.imports.set("System.Net", ["System.Net"]);
906
- sourceFile.imports.set("System.Threading.Tasks", ["System.Threading.Tasks"]);
907
- sourceFile.imports.set("System.Text.Json", ["System.Text.Json"]);
908
- sourceFile.imports.set("System.Text.Json.Serialization", ["System.Text.Json.Serialization"]);
909
- sourceFile.imports.set("Microsoft.AspNetCore.Mvc", ["Microsoft.AspNetCore.Mvc"]);
910
- sourceFile.imports.set(namespace, [namespace]);
911
- sourceFile.meta[this.#nsKey] = namespace;
912
- context = {
913
- namespace: namespace,
914
- file: sourceFile,
915
- resourceName: name,
916
- scope: sourceFile.globalScope,
917
- resourceType: resource,
918
- };
919
- controllers.set(`${namespace}.${name}`, context);
920
- return context;
921
- }
922
- // eslint-disable-next-line no-unused-private-class-members
923
- #getNamespaceFullName(namespace) {
924
- return namespace
925
- ? ensureCSharpIdentifier(this.emitter.getProgram(), namespace, getNamespaceFullName(namespace))
926
- : "TypeSpec";
927
- }
928
- reference(targetDeclaration, pathUp, pathDown, commonScope) {
929
- const resolved = resolveReferenceFromScopes(targetDeclaration, pathDown, pathUp);
930
- return resolved ?? super.reference(targetDeclaration, pathUp, pathDown, commonScope);
931
- }
932
- scalarInstantiation(scalar, name) {
933
- const scalarType = getCSharpTypeForScalar(this.emitter.getProgram(), scalar);
934
- return scalarType.getTypeReference(this.emitter.getContext().scope);
935
- }
936
- scalarDeclaration(scalar, name) {
937
- const scalarType = getCSharpTypeForScalar(this.emitter.getProgram(), scalar);
938
- return scalarType.getTypeReference(this.emitter.getContext().scope);
939
- }
940
- sourceFile(sourceFile) {
941
- if (sourceFile.meta.emitted) {
942
- return sourceFile.meta.emitted;
943
- }
944
- if (sourceFile.meta["skipEmit"]) {
945
- return { path: sourceFile.path, contents: "" };
946
- }
947
- const emittedSourceFile = {
948
- path: sourceFile.path,
949
- contents: "",
950
- };
951
- switch (sourceFile.meta[this.#sourceTypeKey]) {
952
- case CSharpSourceType.Controller:
953
- emittedSourceFile.contents = this.#emitControllerContents(sourceFile);
954
- break;
955
- default:
956
- emittedSourceFile.contents = this.#emitCodeContents(sourceFile);
957
- break;
958
- }
959
- return emittedSourceFile;
960
- }
961
- #emitCodeContents(file) {
962
- const contents = new StringBuilder();
963
- contents.pushLiteralSegment(`${file.meta["nullable"] ? this.#generatedFileHeaderWithNullable : this.#generatedFileHeader}
964
-
965
- ${this.#emitUsings(file)}
966
- `);
967
- for (const decl of file.globalScope.declarations) {
968
- contents.push(decl.value);
969
- }
970
- for (const child of file.globalScope.childScopes) {
971
- if (child.declarations) {
972
- for (const decl of child.declarations) {
973
- contents.push(decl.value);
974
- }
975
- }
976
- }
977
- return contents.segments.join("\n") + "\n";
978
- }
979
- #emitControllerContents(file) {
980
- const namespace = file.meta.namespace;
981
- const contents = new StringBuilder();
982
- contents.push(`${this.#generatedFileHeaderWithNullable}\n\n`);
983
- contents.push(code `${this.#emitUsings(file)}\n`);
984
- contents.push("\n");
985
- contents.push(`namespace ${namespace}.Controllers\n`);
986
- contents.push("{\n");
987
- contents.push("[ApiController]\n");
988
- contents.push(`public partial class ${file.meta["resource"]}: ControllerBase\n`);
989
- contents.push("{\n");
990
- contents.push("\n");
991
- contents.push(`public ${file.meta["resource"]}(I${file.meta.resourceName} operations)\n`);
992
- contents.push("{\n");
993
- contents.push(` ${file.meta.resourceName}Impl = operations;\n`);
994
- contents.push("}");
995
- contents.push("\n");
996
- contents.push(code `internal virtual I${file.meta.resourceName} ${file.meta.resourceName}Impl { get;}\n`);
997
- for (const decl of file.globalScope.declarations) {
998
- contents.push(decl.value + "\n");
999
- }
1000
- contents.push("\n}");
1001
- contents.push("\n}");
1002
- return contents.segments.join("\n") + "\n";
1003
- }
1004
- stringLiteral(string) {
1005
- return this.emitter.result.rawCode(code `"${string.value}"`);
1006
- }
1007
- tupleLiteral(tuple) {
1008
- return this.emitter.result.rawCode(code `{
1009
- ${this.emitter.emitTupleLiteralValues(tuple)}
1010
- }`);
1011
- }
1012
- tupleLiteralValues(tuple) {
1013
- const result = new StringBuilder();
1014
- for (const tupleValue of tuple.values) {
1015
- result.push(code `${this.emitter.emitType(tupleValue)}`);
1016
- }
1017
- return this.emitter.result.rawCode(result.segments.join(",\n"));
1018
- }
1019
- createModelScope(baseScope, namespace) {
1020
- let current = baseScope;
1021
- for (const part of namespace.split(".")) {
1022
- current = this.emitter.createScope({}, getCSharpIdentifier(part), current);
1023
- }
1024
- return current;
1025
- }
1026
- // TODO: remove?
1027
- // eslint-disable-next-line no-unused-private-class-members
1028
- #getTemplateParameters(model) {
1029
- if (!model.templateMapper)
1030
- return "";
1031
- let i = 0;
1032
- const params = new StringBuilder();
1033
- const args = model.templateMapper.args
1034
- .flatMap((parm) => parm)
1035
- .filter((arg) => arg !== null && isKnownReferenceType(this.emitter.getProgram(), arg));
1036
- for (const parameter of args) {
1037
- i++;
1038
- params.push(code `${this.emitter.emitTypeReference(parameter)}`);
1039
- if (i < args.length) {
1040
- params.pushLiteralSegment(",");
1041
- }
1042
- }
1043
- if (params.segments.length > 0)
1044
- return params.reduce();
1045
- return "";
1046
- }
1047
- async writeOutput(sourceFiles) {
1048
- sourceFiles.push(...getSerializationSourceFiles(this.emitter).flatMap((l) => l.source));
1049
- sourceFiles.push(...getProjectDocs(this.emitter, this.#useSwagger, this.#mockRegistrations).flatMap((l) => l.source));
1050
- if (this.#emitMocks === "mocks-and-project-files" || this.#emitMocks === "mocks-only") {
1051
- if (this.#mockRegistrations.size > 0) {
1052
- const mocks = getBusinessLogicImplementations(this.emitter, this.#mockRegistrations, this.#useSwagger, this.#openapiPath);
1053
- sourceFiles.push(...mocks.flatMap((l) => l.source));
1054
- }
1055
- }
1056
- async function shouldWrite(source, exists) {
1057
- return (!source.meta.conditional || options.overwrite === true || !(await exists(source.path)));
1058
- }
1059
- const emittedSourceFiles = [];
1060
- for (const source of sourceFiles) {
1061
- switch (this.#emitterOutputType) {
1062
- case "models":
1063
- {
1064
- switch (source.meta[this.#sourceTypeKey]) {
1065
- case CSharpSourceType.Controller:
1066
- // do nothing
1067
- break;
1068
- default:
1069
- if (await shouldWrite(source, this.#fileExists)) {
1070
- emittedSourceFiles.push(source);
1071
- }
1072
- break;
1073
- }
1074
- }
1075
- break;
1076
- default:
1077
- if (await shouldWrite(source, this.#fileExists)) {
1078
- emittedSourceFiles.push(source);
1079
- }
1080
- break;
1081
- }
1082
- }
1083
- return super.writeOutput(emittedSourceFiles.filter((f) => !f.meta["skipEmit"]));
1084
- }
1085
- }
1086
- function processNameSpace(program, target, service) {
1087
- if (!service)
1088
- service = getService(program, target);
1089
- if (service) {
1090
- for (const [_, model] of target.models) {
1091
- if (!isTemplateDeclaration(model) && !isEmptyResponseModel(program, model)) {
1092
- emitter.emitType(model);
1093
- }
1094
- }
1095
- for (const [_, en] of target.enums) {
1096
- emitter.emitType(en);
1097
- }
1098
- for (const [_, sc] of target.scalars) {
1099
- emitter.emitType(sc);
1100
- }
1101
- for (const [_, iface] of target.interfaces) {
1102
- if (!isTemplateDeclaration(iface)) {
1103
- emitter.emitType(iface);
1104
- }
1105
- }
1106
- if (target.operations.size > 0) {
1107
- // Collect interface operations for a business logic interface and controller
1108
- const nsOps = [];
1109
- for (const [name, op] of target.operations) {
1110
- if (!isTemplateDeclaration(op)) {
1111
- nsOps.push([name, op]);
1112
- }
1113
- }
1114
- const iface = program.checker.createAndFinishType({
1115
- sourceInterfaces: [],
1116
- decorators: [],
1117
- operations: createRekeyableMap(nsOps),
1118
- kind: "Interface",
1119
- name: `${target.name}Operations`,
1120
- namespace: target,
1121
- entityKind: "Type",
1122
- isFinished: true,
1123
- });
1124
- try {
1125
- for (const [_, op] of nsOps) {
1126
- op.interface = iface;
1127
- }
1128
- emitter.emitType(iface);
1129
- }
1130
- finally {
1131
- for (const [_, op] of nsOps) {
1132
- op.interface = undefined;
1133
- }
1134
- target.interfaces.delete(iface.name);
1135
- }
1136
- }
1137
- for (const [_, sub] of target.namespaces) {
1138
- processNameSpace(program, sub, service);
1139
- }
1140
- }
1141
- else {
1142
- for (const [_, sub] of target.namespaces) {
1143
- processNameSpace(program, sub);
1144
- }
1145
- }
1146
- }
1147
- const emitter = createAssetEmitter(context.program, CSharpCodeEmitter, context);
1148
- const ns = context.program.getGlobalNamespaceType();
1149
- const options = emitter.getOptions();
1150
- processNameSpace(context.program, ns);
1151
- if (!doNotEmit) {
1152
- const outputDir = options.emitterOutputDir;
1153
- const generatedDir = path.join(outputDir, "generated");
1154
- await ensureCleanDirectory(context.program, generatedDir);
1155
- function normalizeSlashes(path) {
1156
- return path.replaceAll("\\", "/");
1157
- }
1158
- async function getOpenApiPath() {
1159
- if (options["openapi-path"])
1160
- return options["openapi-path"];
1161
- const openApiSettings = await getOpenApiConfig(context.program);
1162
- const projectDir = resolvePath(context.program.projectRoot, outputDir);
1163
- if (openApiSettings.outputDir) {
1164
- const openApiPath = resolvePath(openApiSettings.outputDir, openApiSettings.fileName || "openapi.yaml");
1165
- return normalizeSlashes(path.relative(projectDir, openApiPath));
1166
- }
1167
- if (openApiSettings.emitted) {
1168
- const baseDir = context.program.compilerOptions.outputDir ||
1169
- resolvePath(context.program.projectRoot, "tsp-output");
1170
- const openApiPath = resolvePath(baseDir, "@typespec", "openapi3", openApiSettings.fileName || "openapi.yaml");
1171
- return normalizeSlashes(path.relative(projectDir, openApiPath));
1172
- }
1173
- return "";
1174
- }
1175
- const openApiPath = await getOpenApiPath();
1176
- const UseSwaggerUI = openApiPath !== "" && options["use-swaggerui"] === true;
1177
- let httpPort;
1178
- let httpsPort;
1179
- if (options["emit-mocks"] !== "none") {
1180
- getScaffoldingHelpers(emitter, UseSwaggerUI, openApiPath, true);
1181
- }
1182
- if (options["emit-mocks"] === "mocks-and-project-files") {
1183
- httpPort = options["http-port"] || (await getFreePort(5000, 5999));
1184
- httpsPort = options["https-port"] || (await getFreePort(7000, 7999));
1185
- getProjectHelpers(emitter, options["project-name"] || "ServiceProject", options["use-swaggerui"] || false, httpPort, httpsPort);
1186
- }
1187
- await emitter.writeOutput();
1188
- const projectDir = normalizeSlashes(path.relative(process.cwd(), resolvePath(outputDir)));
1189
- function trace(message) {
1190
- context.program.trace("http-server-csharp", `hscs-msg: ${message}`);
1191
- }
1192
- trace(`Your project was successfully created at "${projectDir}"`);
1193
- trace(`You can build and start the project using 'dotnet run --project "${projectDir}"'`);
1194
- if (options["use-swaggerui"] === true && httpsPort) {
1195
- trace(`You can browse the swagger UI to test your service using 'start https://localhost:${httpsPort}/swagger/' `);
1196
- }
1197
- if (options["skip-format"] === undefined || options["skip-format"] === false) {
1198
- await execFile("dotnet", [
1199
- "format",
1200
- "whitespace",
1201
- outputDir,
1202
- "--include-generated",
1203
- "--folder",
1204
- ]);
1205
- }
1206
- }
1207
- }
1208
- //# sourceMappingURL=service.js.map