@seamapi/nextlove-sdk-generator 1.4.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 (287) hide show
  1. package/LICENSE.txt +20 -0
  2. package/README.md +16 -0
  3. package/index.d.ts +6 -0
  4. package/index.js +7 -0
  5. package/index.js.map +1 -0
  6. package/lib/cli.d.ts +2 -0
  7. package/lib/cli.js +53 -0
  8. package/lib/cli.js.map +1 -0
  9. package/lib/fs-util/index.d.ts +2 -0
  10. package/lib/fs-util/index.js +3 -0
  11. package/lib/fs-util/index.js.map +1 -0
  12. package/lib/fs-util/populate-fs.d.ts +1 -0
  13. package/lib/fs-util/populate-fs.js +11 -0
  14. package/lib/fs-util/populate-fs.js.map +1 -0
  15. package/lib/fs-util/write-fs.d.ts +1 -0
  16. package/lib/fs-util/write-fs.js +10 -0
  17. package/lib/fs-util/write-fs.js.map +1 -0
  18. package/lib/generate-csharp-sdk/codegen.d.ts +235 -0
  19. package/lib/generate-csharp-sdk/codegen.js +432 -0
  20. package/lib/generate-csharp-sdk/codegen.js.map +1 -0
  21. package/lib/generate-csharp-sdk/constants.d.ts +1 -0
  22. package/lib/generate-csharp-sdk/constants.js +2 -0
  23. package/lib/generate-csharp-sdk/constants.js.map +1 -0
  24. package/lib/generate-csharp-sdk/generate-csharp-sdk.d.ts +1 -0
  25. package/lib/generate-csharp-sdk/generate-csharp-sdk.js +81 -0
  26. package/lib/generate-csharp-sdk/generate-csharp-sdk.js.map +1 -0
  27. package/lib/generate-csharp-sdk/generate-csproj.d.ts +1 -0
  28. package/lib/generate-csharp-sdk/generate-csproj.js +45 -0
  29. package/lib/generate-csharp-sdk/generate-csproj.js.map +1 -0
  30. package/lib/generate-csharp-sdk/templates/dataclass.d.ts +24 -0
  31. package/lib/generate-csharp-sdk/templates/dataclass.js +468 -0
  32. package/lib/generate-csharp-sdk/templates/dataclass.js.map +1 -0
  33. package/lib/generate-csharp-sdk/templates/fs/csharp-testing.sln +34 -0
  34. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/ApiResponse.cs +159 -0
  35. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/ClientUtils.cs +280 -0
  36. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/ExceptionFactory.cs +12 -0
  37. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/GlobalSeamRequestConfiguration.cs +60 -0
  38. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/HttpMethod.cs +29 -0
  39. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/IAsynchronousSeam.cs +142 -0
  40. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/IReadableSeamRequestConfiguration.cs +68 -0
  41. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/ISynchronousSeam.cs +103 -0
  42. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/Multimap.cs +286 -0
  43. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/RequestOptions.cs +74 -0
  44. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/RetryConfiguration.cs +21 -0
  45. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/Seam.cs +1070 -0
  46. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/SeamException.cs +64 -0
  47. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/SeamRequestConfiguration.cs +662 -0
  48. package/lib/generate-csharp-sdk/templates/fs/src/Seam/Model/AsbtractModelSchema.cs +62 -0
  49. package/lib/generate-php-sdk/generate-php-sdk.d.ts +1 -0
  50. package/lib/generate-php-sdk/generate-php-sdk.js +127 -0
  51. package/lib/generate-php-sdk/generate-php-sdk.js.map +1 -0
  52. package/lib/generate-php-sdk/index.d.ts +1 -0
  53. package/lib/generate-php-sdk/index.js +2 -0
  54. package/lib/generate-php-sdk/index.js.map +1 -0
  55. package/lib/generate-php-sdk/templates/composer.json.template.d.ts +2 -0
  56. package/lib/generate-php-sdk/templates/composer.json.template.js +25 -0
  57. package/lib/generate-php-sdk/templates/composer.json.template.js.map +1 -0
  58. package/lib/generate-php-sdk/templates/env.example.template.d.ts +2 -0
  59. package/lib/generate-php-sdk/templates/env.example.template.js +4 -0
  60. package/lib/generate-php-sdk/templates/env.example.template.js.map +1 -0
  61. package/lib/generate-php-sdk/templates/gitignore.template.d.ts +2 -0
  62. package/lib/generate-php-sdk/templates/gitignore.template.js +6 -0
  63. package/lib/generate-php-sdk/templates/gitignore.template.js.map +1 -0
  64. package/lib/generate-php-sdk/templates/package.json.template.d.ts +2 -0
  65. package/lib/generate-php-sdk/templates/package.json.template.js +12 -0
  66. package/lib/generate-php-sdk/templates/package.json.template.js.map +1 -0
  67. package/lib/generate-php-sdk/templates/readme.md.template.d.ts +2 -0
  68. package/lib/generate-php-sdk/templates/readme.md.template.js +86 -0
  69. package/lib/generate-php-sdk/templates/readme.md.template.js.map +1 -0
  70. package/lib/generate-php-sdk/templates/smoke-test.template.d.ts +2 -0
  71. package/lib/generate-php-sdk/templates/smoke-test.template.js +30 -0
  72. package/lib/generate-php-sdk/templates/smoke-test.template.js.map +1 -0
  73. package/lib/generate-php-sdk/templates/test-fixture.template.d.ts +2 -0
  74. package/lib/generate-php-sdk/templates/test-fixture.template.js +21 -0
  75. package/lib/generate-php-sdk/templates/test-fixture.template.js.map +1 -0
  76. package/lib/generate-php-sdk/utils/deep-extract-resource-object-schemas.d.ts +16 -0
  77. package/lib/generate-php-sdk/utils/deep-extract-resource-object-schemas.js +97 -0
  78. package/lib/generate-php-sdk/utils/deep-extract-resource-object-schemas.js.map +1 -0
  79. package/lib/generate-php-sdk/utils/deep-flatten-one-of-and-all-of-schema.d.ts +2 -0
  80. package/lib/generate-php-sdk/utils/deep-flatten-one-of-and-all-of-schema.js +95 -0
  81. package/lib/generate-php-sdk/utils/deep-flatten-one-of-and-all-of-schema.js.map +1 -0
  82. package/lib/generate-php-sdk/utils/generate-resource-object-class.d.ts +8 -0
  83. package/lib/generate-php-sdk/utils/generate-resource-object-class.js +73 -0
  84. package/lib/generate-php-sdk/utils/generate-resource-object-class.js.map +1 -0
  85. package/lib/generate-php-sdk/utils/generate-seam-client.d.ts +7 -0
  86. package/lib/generate-php-sdk/utils/generate-seam-client.js +103 -0
  87. package/lib/generate-php-sdk/utils/generate-seam-client.js.map +1 -0
  88. package/lib/generate-php-sdk/utils/get-php-type.d.ts +1 -0
  89. package/lib/generate-php-sdk/utils/get-php-type.js +17 -0
  90. package/lib/generate-php-sdk/utils/get-php-type.js.map +1 -0
  91. package/lib/generate-php-sdk/utils/php-client.d.ts +31 -0
  92. package/lib/generate-php-sdk/utils/php-client.js +130 -0
  93. package/lib/generate-php-sdk/utils/php-client.js.map +1 -0
  94. package/lib/generate-python-sdk/class-file.d.ts +20 -0
  95. package/lib/generate-python-sdk/class-file.js +75 -0
  96. package/lib/generate-python-sdk/class-file.js.map +1 -0
  97. package/lib/generate-python-sdk/generate-python-sdk.d.ts +1 -0
  98. package/lib/generate-python-sdk/generate-python-sdk.js +117 -0
  99. package/lib/generate-python-sdk/generate-python-sdk.js.map +1 -0
  100. package/lib/generate-python-sdk/index.d.ts +1 -0
  101. package/lib/generate-python-sdk/index.js +2 -0
  102. package/lib/generate-python-sdk/index.js.map +1 -0
  103. package/lib/generate-python-sdk/map-python-type.d.ts +2 -0
  104. package/lib/generate-python-sdk/map-python-type.js +26 -0
  105. package/lib/generate-python-sdk/map-python-type.js.map +1 -0
  106. package/lib/generate-python-sdk/templates/conftest.py.template.d.ts +2 -0
  107. package/lib/generate-python-sdk/templates/conftest.py.template.js +12 -0
  108. package/lib/generate-python-sdk/templates/conftest.py.template.js.map +1 -0
  109. package/lib/generate-python-sdk/templates/pyproject.toml.template.d.ts +2 -0
  110. package/lib/generate-python-sdk/templates/pyproject.toml.template.js +21 -0
  111. package/lib/generate-python-sdk/templates/pyproject.toml.template.js.map +1 -0
  112. package/lib/generate-python-sdk/templates/readme.md.template.d.ts +2 -0
  113. package/lib/generate-python-sdk/templates/readme.md.template.js +48 -0
  114. package/lib/generate-python-sdk/templates/readme.md.template.js.map +1 -0
  115. package/lib/generate-python-sdk/templates/routes.py.template.d.ts +2 -0
  116. package/lib/generate-python-sdk/templates/routes.py.template.js +13 -0
  117. package/lib/generate-python-sdk/templates/routes.py.template.js.map +1 -0
  118. package/lib/generate-python-sdk/templates/seam.py.template.d.ts +2 -0
  119. package/lib/generate-python-sdk/templates/seam.py.template.js +74 -0
  120. package/lib/generate-python-sdk/templates/seam.py.template.js.map +1 -0
  121. package/lib/generate-python-sdk/templates/snippets/abstract-routes.template.d.ts +2 -0
  122. package/lib/generate-python-sdk/templates/snippets/abstract-routes.template.js +9 -0
  123. package/lib/generate-python-sdk/templates/snippets/abstract-routes.template.js.map +1 -0
  124. package/lib/generate-python-sdk/templates/snippets/abstract-seam.template.d.ts +2 -0
  125. package/lib/generate-python-sdk/templates/snippets/abstract-seam.template.js +9 -0
  126. package/lib/generate-python-sdk/templates/snippets/abstract-seam.template.js.map +1 -0
  127. package/lib/generate-python-sdk/templates/snippets/resource-dataclass.template.d.ts +5 -0
  128. package/lib/generate-python-sdk/templates/snippets/resource-dataclass.template.js +10 -0
  129. package/lib/generate-python-sdk/templates/snippets/resource-dataclass.template.js.map +1 -0
  130. package/lib/generate-python-sdk/templates/test_smoke.py.template.d.ts +2 -0
  131. package/lib/generate-python-sdk/templates/test_smoke.py.template.js +13 -0
  132. package/lib/generate-python-sdk/templates/test_smoke.py.template.js.map +1 -0
  133. package/lib/generate-python-sdk/templates/utils/deep_attr_dict.py.template.d.ts +2 -0
  134. package/lib/generate-python-sdk/templates/utils/deep_attr_dict.py.template.js +28 -0
  135. package/lib/generate-python-sdk/templates/utils/deep_attr_dict.py.template.js.map +1 -0
  136. package/lib/generate-ruby-sdk/generate-ruby-sdk.d.ts +1 -0
  137. package/lib/generate-ruby-sdk/generate-ruby-sdk.js +132 -0
  138. package/lib/generate-ruby-sdk/generate-ruby-sdk.js.map +1 -0
  139. package/lib/generate-ruby-sdk/index.d.ts +1 -0
  140. package/lib/generate-ruby-sdk/index.js +2 -0
  141. package/lib/generate-ruby-sdk/index.js.map +1 -0
  142. package/lib/generate-ruby-sdk/request.rb.template.d.ts +1 -0
  143. package/lib/generate-ruby-sdk/request.rb.template.js +2 -0
  144. package/lib/generate-ruby-sdk/request.rb.template.js.map +1 -0
  145. package/lib/generate-ruby-sdk/ruby-client.d.ts +35 -0
  146. package/lib/generate-ruby-sdk/ruby-client.js +59 -0
  147. package/lib/generate-ruby-sdk/ruby-client.js.map +1 -0
  148. package/lib/generate-ruby-sdk/templates/base_client.rb.template.d.ts +2 -0
  149. package/lib/generate-ruby-sdk/templates/base_client.rb.template.js +22 -0
  150. package/lib/generate-ruby-sdk/templates/base_client.rb.template.js.map +1 -0
  151. package/lib/generate-ruby-sdk/templates/base_resource.rb.template.d.ts +2 -0
  152. package/lib/generate-ruby-sdk/templates/base_resource.rb.template.js +59 -0
  153. package/lib/generate-ruby-sdk/templates/base_resource.rb.template.js.map +1 -0
  154. package/lib/generate-ruby-sdk/templates/client.rb.template.d.ts +2 -0
  155. package/lib/generate-ruby-sdk/templates/client.rb.template.js +74 -0
  156. package/lib/generate-ruby-sdk/templates/client.rb.template.js.map +1 -0
  157. package/lib/generate-ruby-sdk/templates/gemfile.template.d.ts +2 -0
  158. package/lib/generate-ruby-sdk/templates/gemfile.template.js +7 -0
  159. package/lib/generate-ruby-sdk/templates/gemfile.template.js.map +1 -0
  160. package/lib/generate-ruby-sdk/templates/logger.rb.template.d.ts +2 -0
  161. package/lib/generate-ruby-sdk/templates/logger.rb.template.js +13 -0
  162. package/lib/generate-ruby-sdk/templates/logger.rb.template.js.map +1 -0
  163. package/lib/generate-ruby-sdk/templates/rakefile.template.d.ts +2 -0
  164. package/lib/generate-ruby-sdk/templates/rakefile.template.js +23 -0
  165. package/lib/generate-ruby-sdk/templates/rakefile.template.js.map +1 -0
  166. package/lib/generate-ruby-sdk/templates/readme.md.template.d.ts +2 -0
  167. package/lib/generate-ruby-sdk/templates/readme.md.template.js +184 -0
  168. package/lib/generate-ruby-sdk/templates/readme.md.template.js.map +1 -0
  169. package/lib/generate-ruby-sdk/templates/request.rb.template.d.ts +2 -0
  170. package/lib/generate-ruby-sdk/templates/request.rb.template.js +71 -0
  171. package/lib/generate-ruby-sdk/templates/request.rb.template.js.map +1 -0
  172. package/lib/generate-ruby-sdk/templates/resource_error.rb.template.d.ts +2 -0
  173. package/lib/generate-ruby-sdk/templates/resource_error.rb.template.js +8 -0
  174. package/lib/generate-ruby-sdk/templates/resource_error.rb.template.js.map +1 -0
  175. package/lib/generate-ruby-sdk/templates/resource_errors_support.rb.template.d.ts +2 -0
  176. package/lib/generate-ruby-sdk/templates/resource_errors_support.rb.template.js +10 -0
  177. package/lib/generate-ruby-sdk/templates/resource_errors_support.rb.template.js.map +1 -0
  178. package/lib/generate-ruby-sdk/templates/resource_warning.rb.template.d.ts +2 -0
  179. package/lib/generate-ruby-sdk/templates/resource_warning.rb.template.js +8 -0
  180. package/lib/generate-ruby-sdk/templates/resource_warning.rb.template.js.map +1 -0
  181. package/lib/generate-ruby-sdk/templates/resource_warnings_support.rb.template.d.ts +2 -0
  182. package/lib/generate-ruby-sdk/templates/resource_warnings_support.rb.template.js +10 -0
  183. package/lib/generate-ruby-sdk/templates/resource_warnings_support.rb.template.js.map +1 -0
  184. package/lib/generate-ruby-sdk/templates/seamapi.gemspec.template.d.ts +2 -0
  185. package/lib/generate-ruby-sdk/templates/seamapi.gemspec.template.js +41 -0
  186. package/lib/generate-ruby-sdk/templates/seamapi.gemspec.template.js.map +1 -0
  187. package/lib/generate-ruby-sdk/templates/snippets/resource.rb.template.d.ts +6 -0
  188. package/lib/generate-ruby-sdk/templates/snippets/resource.rb.template.js +15 -0
  189. package/lib/generate-ruby-sdk/templates/snippets/resource.rb.template.js.map +1 -0
  190. package/lib/generate-ruby-sdk/templates/version.rb.template.d.ts +2 -0
  191. package/lib/generate-ruby-sdk/templates/version.rb.template.js +6 -0
  192. package/lib/generate-ruby-sdk/templates/version.rb.template.js.map +1 -0
  193. package/lib/index.d.ts +2 -0
  194. package/lib/index.js +3 -0
  195. package/lib/index.js.map +1 -0
  196. package/lib/openapi/flatten-obj-schema.d.ts +5 -0
  197. package/lib/openapi/flatten-obj-schema.js +86 -0
  198. package/lib/openapi/flatten-obj-schema.js.map +1 -0
  199. package/lib/openapi/get-parameter-and-response-schema.d.ts +20 -0
  200. package/lib/openapi/get-parameter-and-response-schema.js +42 -0
  201. package/lib/openapi/get-parameter-and-response-schema.js.map +1 -0
  202. package/lib/openapi/index.d.ts +2 -0
  203. package/lib/openapi/index.js +3 -0
  204. package/lib/openapi/index.js.map +1 -0
  205. package/lib/types.d.ts +91 -0
  206. package/lib/types.js +2 -0
  207. package/lib/types.js.map +1 -0
  208. package/package.json +95 -0
  209. package/src/index.ts +6 -0
  210. package/src/lib/cli.ts +71 -0
  211. package/src/lib/fs-util/index.ts +2 -0
  212. package/src/lib/fs-util/populate-fs.ts +14 -0
  213. package/src/lib/fs-util/write-fs.ts +10 -0
  214. package/src/lib/generate-csharp-sdk/codegen.ts +648 -0
  215. package/src/lib/generate-csharp-sdk/constants.ts +1 -0
  216. package/src/lib/generate-csharp-sdk/generate-csharp-sdk.ts +126 -0
  217. package/src/lib/generate-csharp-sdk/generate-csproj.ts +45 -0
  218. package/src/lib/generate-csharp-sdk/templates/dataclass.ts +973 -0
  219. package/src/lib/generate-csharp-sdk/templates/fs/csharp-testing.sln +34 -0
  220. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/ApiResponse.cs +159 -0
  221. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/ClientUtils.cs +280 -0
  222. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/ExceptionFactory.cs +12 -0
  223. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/GlobalSeamRequestConfiguration.cs +60 -0
  224. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/HttpMethod.cs +29 -0
  225. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/IAsynchronousSeam.cs +142 -0
  226. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/IReadableSeamRequestConfiguration.cs +68 -0
  227. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/ISynchronousSeam.cs +103 -0
  228. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/Multimap.cs +286 -0
  229. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/RequestOptions.cs +74 -0
  230. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/RetryConfiguration.cs +21 -0
  231. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/Seam.cs +1070 -0
  232. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/SeamException.cs +64 -0
  233. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Client/SeamRequestConfiguration.cs +662 -0
  234. package/src/lib/generate-csharp-sdk/templates/fs/src/Seam/Model/AsbtractModelSchema.cs +62 -0
  235. package/src/lib/generate-php-sdk/generate-php-sdk.ts +176 -0
  236. package/src/lib/generate-php-sdk/index.ts +1 -0
  237. package/src/lib/generate-php-sdk/templates/composer.json.template.ts +24 -0
  238. package/src/lib/generate-php-sdk/templates/env.example.template.ts +3 -0
  239. package/src/lib/generate-php-sdk/templates/gitignore.template.ts +5 -0
  240. package/src/lib/generate-php-sdk/templates/package.json.template.ts +11 -0
  241. package/src/lib/generate-php-sdk/templates/readme.md.template.ts +85 -0
  242. package/src/lib/generate-php-sdk/templates/smoke-test.template.ts +29 -0
  243. package/src/lib/generate-php-sdk/templates/test-fixture.template.ts +20 -0
  244. package/src/lib/generate-php-sdk/utils/deep-extract-resource-object-schemas.ts +160 -0
  245. package/src/lib/generate-php-sdk/utils/deep-flatten-one-of-and-all-of-schema.ts +128 -0
  246. package/src/lib/generate-php-sdk/utils/generate-resource-object-class.ts +105 -0
  247. package/src/lib/generate-php-sdk/utils/generate-seam-client.ts +115 -0
  248. package/src/lib/generate-php-sdk/utils/get-php-type.ts +21 -0
  249. package/src/lib/generate-php-sdk/utils/php-client.ts +189 -0
  250. package/src/lib/generate-python-sdk/class-file.ts +114 -0
  251. package/src/lib/generate-python-sdk/generate-python-sdk.ts +147 -0
  252. package/src/lib/generate-python-sdk/index.ts +1 -0
  253. package/src/lib/generate-python-sdk/map-python-type.ts +29 -0
  254. package/src/lib/generate-python-sdk/templates/conftest.py.template.ts +11 -0
  255. package/src/lib/generate-python-sdk/templates/pyproject.toml.template.ts +20 -0
  256. package/src/lib/generate-python-sdk/templates/readme.md.template.ts +47 -0
  257. package/src/lib/generate-python-sdk/templates/routes.py.template.ts +13 -0
  258. package/src/lib/generate-python-sdk/templates/seam.py.template.ts +73 -0
  259. package/src/lib/generate-python-sdk/templates/snippets/abstract-routes.template.ts +9 -0
  260. package/src/lib/generate-python-sdk/templates/snippets/abstract-seam.template.ts +8 -0
  261. package/src/lib/generate-python-sdk/templates/snippets/resource-dataclass.template.ts +15 -0
  262. package/src/lib/generate-python-sdk/templates/test_smoke.py.template.ts +12 -0
  263. package/src/lib/generate-python-sdk/templates/utils/deep_attr_dict.py.template.ts +27 -0
  264. package/src/lib/generate-ruby-sdk/generate-ruby-sdk.ts +153 -0
  265. package/src/lib/generate-ruby-sdk/index.ts +1 -0
  266. package/src/lib/generate-ruby-sdk/request.rb.template.ts +0 -0
  267. package/src/lib/generate-ruby-sdk/ruby-client.ts +81 -0
  268. package/src/lib/generate-ruby-sdk/templates/base_client.rb.template.ts +21 -0
  269. package/src/lib/generate-ruby-sdk/templates/base_resource.rb.template.ts +58 -0
  270. package/src/lib/generate-ruby-sdk/templates/client.rb.template.ts +73 -0
  271. package/src/lib/generate-ruby-sdk/templates/gemfile.template.ts +6 -0
  272. package/src/lib/generate-ruby-sdk/templates/logger.rb.template.ts +12 -0
  273. package/src/lib/generate-ruby-sdk/templates/rakefile.template.ts +22 -0
  274. package/src/lib/generate-ruby-sdk/templates/readme.md.template.ts +183 -0
  275. package/src/lib/generate-ruby-sdk/templates/request.rb.template.ts +70 -0
  276. package/src/lib/generate-ruby-sdk/templates/resource_error.rb.template.ts +7 -0
  277. package/src/lib/generate-ruby-sdk/templates/resource_errors_support.rb.template.ts +9 -0
  278. package/src/lib/generate-ruby-sdk/templates/resource_warning.rb.template.ts +7 -0
  279. package/src/lib/generate-ruby-sdk/templates/resource_warnings_support.rb.template.ts +9 -0
  280. package/src/lib/generate-ruby-sdk/templates/seamapi.gemspec.template.ts +40 -0
  281. package/src/lib/generate-ruby-sdk/templates/snippets/resource.rb.template.ts +24 -0
  282. package/src/lib/generate-ruby-sdk/templates/version.rb.template.ts +5 -0
  283. package/src/lib/index.ts +2 -0
  284. package/src/lib/openapi/flatten-obj-schema.ts +124 -0
  285. package/src/lib/openapi/get-parameter-and-response-schema.ts +59 -0
  286. package/src/lib/openapi/index.ts +2 -0
  287. package/src/lib/types.ts +96 -0
@@ -0,0 +1,973 @@
1
+ import { camelCase, snakeCase, pascalCase } from "change-case"
2
+ import * as cs from "../codegen.js"
3
+ import {
4
+ deepFlattenAllOfSchema,
5
+ type AllOfSchema,
6
+ type ObjSchema,
7
+ type OneOfSchema,
8
+ type PropertySchema,
9
+ type RefSchema,
10
+ } from "@seamapi/nextlove-sdk-generator"
11
+ import assert from "assert"
12
+ import { GLOBAL_NAMESPACE } from "../constants.js"
13
+
14
+ const FALLBACK_TYPE = new cs.TypeNode(cs.TokenNode.TYPE_OBJECT, true)
15
+
16
+ export type RouteInfo = {
17
+ method_name: string
18
+ path: string
19
+ parameter_schema: ObjSchema
20
+ response_obj_type: string | undefined
21
+ response_arr_type: string | undefined
22
+ nullable: boolean
23
+ return_path: string
24
+ namespace: string[]
25
+ }
26
+
27
+ export const DATA_CLASS_IMPORT_BLOCKS = new cs.StatementBlock([
28
+ new cs.UsingStatement(["System", "Runtime", "Serialization"]),
29
+ new cs.UsingStatement(["System", "Text"]),
30
+ new cs.UsingStatement(["Newtonsoft", "Json"]),
31
+ new cs.UsingStatement(["Newtonsoft", "Json", "Converters"]),
32
+ new cs.UsingStatement(["Newtonsoft", "Json", "Linq"]),
33
+ new cs.UsingStatement(["JsonSubTypes"]),
34
+ ])
35
+
36
+ export const API_IMPORT_BLOCKS = new cs.StatementBlock([
37
+ ...DATA_CLASS_IMPORT_BLOCKS.statements,
38
+ new cs.UsingStatement([...GLOBAL_NAMESPACE, "Client"]),
39
+ new cs.UsingStatement([...GLOBAL_NAMESPACE, "Model"]),
40
+ ])
41
+
42
+ const wrapNamespace = (statements: cs.Statement[], namespace?: string[]) => {
43
+ if (!namespace || namespace.length === 0) {
44
+ return new cs.StatementBlock(statements)
45
+ }
46
+
47
+ return new cs.NamespaceBlock(
48
+ new cs.NamespaceNode(namespace),
49
+ statements.map((s) => new cs.StatementBlock([s]))
50
+ )
51
+ }
52
+
53
+ const getToStringMethod = (
54
+ _className: string,
55
+ _properties: [string, PropertySchema][]
56
+ ): cs.MethodDeclaration => {
57
+ const template = `
58
+ JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(null);
59
+
60
+ StringWriter stringWriter = new StringWriter(
61
+ new StringBuilder(256),
62
+ System.Globalization.CultureInfo.InvariantCulture
63
+ );
64
+ using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
65
+ {
66
+ jsonTextWriter.IndentChar = ' ';
67
+ jsonTextWriter.Indentation = 2;
68
+ jsonTextWriter.Formatting = Formatting.Indented;
69
+ jsonSerializer.Serialize(jsonTextWriter, this, null);
70
+ }
71
+
72
+ return stringWriter.ToString();
73
+ `.trim()
74
+
75
+ return new cs.MethodDeclaration(
76
+ new cs.TypeNode(cs.TokenNode.TYPE_STRING),
77
+ new cs.MethodNode(new cs.TokenNode("ToString"), []),
78
+ new cs.CurlyBlock([
79
+ new cs.StatementBlock([new cs.RawStatement(template, false)]),
80
+ ]),
81
+ new cs.VisibilityModifiers(["public", "override"])
82
+ )
83
+ }
84
+
85
+ export const generateDataclassFileForSchema = (
86
+ name: string,
87
+ schema: SupportedPropertySchema,
88
+ resource_type: "response" | "request" | "model",
89
+ namespace?: string[]
90
+ ) => {
91
+ const className = pascalCase(name)
92
+
93
+ const classes = generateDataclassesForSchema(
94
+ className,
95
+ schema,
96
+ resource_type,
97
+ namespace
98
+ )
99
+
100
+ return {
101
+ classFile: new cs.CSharpFile(
102
+ [
103
+ DATA_CLASS_IMPORT_BLOCKS,
104
+ wrapNamespace(classes.classDefs, namespace),
105
+ ].map((s) => new cs.StatementBlock([s]))
106
+ ),
107
+ name: className,
108
+ }
109
+ }
110
+
111
+ export const generateDataclassFileForRoutes = (
112
+ class_name: string,
113
+ routes: RouteInfo[],
114
+ namespace?: string[]
115
+ ) => {
116
+ const classStatements: cs.Statement[] = []
117
+
118
+ const seamInterfaceType = new cs.TypeNode(
119
+ new cs.TokenNode("ISeamClient"),
120
+ false
121
+ )
122
+ const seamInterfaceName = new cs.TokenNode("_seam")
123
+
124
+ const seamClient = new cs.FieldDeclaration(
125
+ seamInterfaceType,
126
+ seamInterfaceName,
127
+ undefined,
128
+ new cs.VisibilityModifiers(["private"])
129
+ )
130
+
131
+ const constructor = new cs.MethodDeclaration(
132
+ undefined,
133
+ new cs.MethodNode(new cs.TokenNode(class_name), [
134
+ new cs.ParameterNode(
135
+ new cs.TypeNode(new cs.TokenNode("ISeamClient")),
136
+ new cs.TokenNode("seam")
137
+ ),
138
+ ]),
139
+ new cs.CurlyBlock([
140
+ new cs.StatementBlock([
141
+ new cs.AssignStatement(seamInterfaceName, new cs.TokenNode("seam")),
142
+ ]),
143
+ ]),
144
+ new cs.VisibilityModifiers(["public"])
145
+ )
146
+
147
+ classStatements.push(seamClient, constructor)
148
+
149
+ for (const route of routes) {
150
+ const {
151
+ method_name,
152
+ path,
153
+ response_obj_type,
154
+ response_arr_type,
155
+ parameter_schema,
156
+ return_path,
157
+ nullable,
158
+ } = route
159
+
160
+ const request = generateDataclassesForObjectOrRefSchema(
161
+ pascalCase([method_name, "request"].join("_")),
162
+ parameter_schema,
163
+ "request"
164
+ )
165
+
166
+ if (!response_obj_type && !response_arr_type) {
167
+ // TODO: support non-named response types
168
+ throw new Error("Invalid response type")
169
+ }
170
+
171
+ const responseType = new cs.TypeNode(
172
+ response_arr_type
173
+ ? new cs.TokenNodeGeneric("List", [
174
+ new cs.TypeNode(
175
+ new cs.TokenNode(pascalCase(response_arr_type)),
176
+ nullable
177
+ ),
178
+ ])
179
+ : new cs.TokenNode(pascalCase(response_obj_type!), nullable)
180
+ )
181
+
182
+ const response = generateDataclassesForSchema(
183
+ pascalCase([method_name, "response"].join("_")),
184
+ {
185
+ type: "object",
186
+ required: [],
187
+ properties: {
188
+ [pascalCase(return_path)]: {
189
+ $ref: responseType.serialize(new cs.CompilerCtx()),
190
+ nullable,
191
+ },
192
+ },
193
+ },
194
+ "response"
195
+ )
196
+
197
+ const requestOptions = new cs.TokenNode("requestOptions")
198
+ const requestObj = new cs.TokenNode("request")
199
+
200
+ const getMethod = (isAsync: boolean) => {
201
+ const asyncPostfix = isAsync ? "Async" : ""
202
+
203
+ const methodName = new cs.TokenNode(
204
+ pascalCase(method_name) + asyncPostfix
205
+ )
206
+
207
+ const wrapTypeTask = (type: cs.TypeNode) =>
208
+ isAsync
209
+ ? new cs.TypeNode(
210
+ new cs.TokenNode("Task"),
211
+ undefined,
212
+ new cs.TypeArgumentsNode([type])
213
+ )
214
+ : type
215
+
216
+ const wrapAwait = (node: cs.CSharpNode) =>
217
+ isAsync ? new cs.ParanthesisNode(new cs.AwaitNode(node)) : node
218
+
219
+ const call = new cs.TokenNodeApplyFunction(
220
+ new cs.AccessChain([
221
+ seamInterfaceName,
222
+ new cs.TokenNode("Post" + asyncPostfix),
223
+ ]),
224
+ [new cs.Literal(path), requestOptions],
225
+ new cs.TypeArgumentsNode([
226
+ new cs.TypeNode(new cs.TokenNode(response.className)),
227
+ ])
228
+ )
229
+
230
+ const result = new cs.AccessChain([
231
+ wrapAwait(call),
232
+ new cs.TokenNode("Data"),
233
+ new cs.TokenNode(pascalCase(return_path)),
234
+ ])
235
+
236
+ const methodSimple = new cs.MethodDeclaration(
237
+ wrapTypeTask(responseType),
238
+ new cs.MethodNode(methodName, [
239
+ new cs.ParameterNode(
240
+ new cs.TypeNode(new cs.TokenNode(request.className)),
241
+ requestObj
242
+ ),
243
+ ]),
244
+ new cs.CurlyBlock([
245
+ new cs.StatementBlock([
246
+ // var requestOptions = new RequestOptions();
247
+ new cs.AssignStatement(
248
+ new cs.CompositeNode([new cs.TokenNode("var"), requestOptions]),
249
+ new cs.ApplyConstructorNode(
250
+ new cs.TokenNode("RequestOptions"),
251
+ []
252
+ )
253
+ ),
254
+ // requestOptions.Data = request
255
+ new cs.AssignStatement(
256
+ new cs.AccessChain([requestOptions, new cs.TokenNode("Data")]),
257
+ requestObj
258
+ ),
259
+ // return seam.Post<responseType>(route, requestOptions).Data;
260
+ new cs.ReturnStatement(result),
261
+ ]),
262
+ ]),
263
+ new cs.VisibilityModifiers([
264
+ "public",
265
+ ...(isAsync ? ["async" as const] : []),
266
+ ])
267
+ )
268
+
269
+ const methodWithProperties = new cs.MethodDeclaration(
270
+ wrapTypeTask(responseType),
271
+ new cs.MethodNode(methodName, request.parameterDefs),
272
+ new cs.CurlyBlock(
273
+ [
274
+ new cs.ReturnStatement(
275
+ wrapAwait(
276
+ new cs.TokenNodeApplyFunction(methodName, [
277
+ new cs.ApplyConstructorNode(
278
+ new cs.TokenNode(request.className),
279
+ request.parameterDefs.map(
280
+ (pd) =>
281
+ new cs.RawNode(`${pd.name.token}: ${pd.name.token}`)
282
+ )
283
+ ),
284
+ ])
285
+ )
286
+ ),
287
+ ].map((s) => new cs.StatementBlock([s]))
288
+ ),
289
+ new cs.VisibilityModifiers([
290
+ "public",
291
+ ...(isAsync ? ["async" as const] : []),
292
+ ])
293
+ )
294
+
295
+ return [methodSimple, methodWithProperties]
296
+ }
297
+
298
+ classStatements.push(
299
+ ...[
300
+ ...request.classDefs,
301
+ ...response.classDefs,
302
+ ...getMethod(false),
303
+ ...getMethod(true),
304
+ ]
305
+ )
306
+ }
307
+
308
+ const cl = new cs.Class(
309
+ new cs.ClassDeclarationSpecifier(
310
+ new cs.TokenNode(pascalCase(class_name)),
311
+ undefined,
312
+ new cs.VisibilityModifiers(["public"])
313
+ ),
314
+ classStatements.map((s) => new cs.StatementBlock([s]))
315
+ )
316
+
317
+ const extendedClass = new cs.Class(
318
+ new cs.ClassDeclarationSpecifier(
319
+ new cs.TokenNode("SeamClient"),
320
+ undefined,
321
+ new cs.VisibilityModifiers(["public", "partial"])
322
+ ),
323
+ [
324
+ new cs.StatementBlock([
325
+ new cs.NodeStatement(
326
+ new cs.CompositeNode([
327
+ new cs.TokenNode("public"),
328
+ new cs.AccessChain([
329
+ new cs.TokenNode("Api"),
330
+ new cs.TokenNode(pascalCase(class_name)),
331
+ ]),
332
+ new cs.TokenNode(pascalCase(class_name)),
333
+ new cs.TokenNode("=>"),
334
+ new cs.TokenNodeApplyFunction(new cs.TokenNode("new"), [
335
+ new cs.TokenNode("this"),
336
+ ]),
337
+ ])
338
+ ),
339
+ ]),
340
+ ]
341
+ )
342
+
343
+ const extendedInterface = new cs.Class(
344
+ new cs.ClassDeclarationSpecifier(
345
+ new cs.TokenNode("ISeamClient"),
346
+ undefined,
347
+ new cs.VisibilityModifiers(["public", "partial"]),
348
+ new cs.TokenNode("interface")
349
+ ),
350
+ [
351
+ new cs.StatementBlock([
352
+ new cs.NodeStatement(
353
+ new cs.CompositeNode([
354
+ new cs.TokenNode("public"),
355
+ new cs.AccessChain([
356
+ new cs.TokenNode("Api"),
357
+ new cs.TokenNode(pascalCase(class_name)),
358
+ ]),
359
+ new cs.TokenNode(pascalCase(class_name)),
360
+ new cs.CurlyBlock(
361
+ [new cs.NodeStatement(new cs.TokenNode("get"))].map(
362
+ (s) => new cs.StatementBlock([s])
363
+ )
364
+ ),
365
+ ]),
366
+ false
367
+ ),
368
+ ]),
369
+ ]
370
+ )
371
+
372
+ return {
373
+ classFile: new cs.CSharpFile(
374
+ [
375
+ API_IMPORT_BLOCKS,
376
+ wrapNamespace([cl], namespace),
377
+ wrapNamespace(
378
+ [extendedClass, extendedInterface],
379
+ [...GLOBAL_NAMESPACE, "Client"]
380
+ ),
381
+ ].map((s) => new cs.StatementBlock([s]))
382
+ ),
383
+ className: class_name,
384
+ }
385
+ }
386
+
387
+ type SupportedPropertySchema = Exclude<PropertySchema, AllOfSchema>
388
+
389
+ type GeneratedDataclassResult = {
390
+ className: string
391
+ classDefs: cs.Statement[]
392
+ parameterDefs?: cs.ParameterNode[]
393
+ propertyDefs?: cs.Statement[]
394
+ }
395
+
396
+ const generateDataclassesForSchema = (
397
+ name: string,
398
+ schema: SupportedPropertySchema,
399
+ resource_type: "response" | "request" | "model",
400
+ namespace?: string[]
401
+ ) => {
402
+ if ("oneOf" in schema) {
403
+ return generateDataclassesForOneOfSchema(
404
+ name,
405
+ schema,
406
+ resource_type,
407
+ namespace
408
+ )
409
+ }
410
+
411
+ if ("$ref" in schema || schema.type === "object") {
412
+ return generateDataclassesForObjectOrRefSchema(
413
+ name,
414
+ schema,
415
+ resource_type,
416
+ namespace
417
+ )
418
+ }
419
+
420
+ throw new Error(
421
+ "Unsupported schema: " +
422
+ JSON.stringify(
423
+ {
424
+ schema,
425
+ name,
426
+ },
427
+ null,
428
+ 2
429
+ )
430
+ )
431
+ }
432
+
433
+ const generateEnumDefs = (
434
+ property_name: string,
435
+ nullable: boolean,
436
+ enumValues: (string | number)[],
437
+ ty: "number" | "string",
438
+ root_name: string
439
+ ) => {
440
+ const enumName = pascalCase(property_name + "Enum")
441
+
442
+ const enumNode = new cs.Enum(
443
+ new cs.EnumDeclarationSpecifier(
444
+ new cs.TokenNode(enumName),
445
+ new cs.VisibilityModifiers(["public"])
446
+ ),
447
+ enumValues
448
+ .map(
449
+ (enumValue, i) =>
450
+ new cs.AnnotatedStatement(
451
+ "EnumMember",
452
+ new cs.AssignStatement(
453
+ new cs.TokenNode(
454
+ safeWrapEnumValue(
455
+ typeof enumValue === "string"
456
+ ? pascalCase(enumValue)
457
+ : enumName + i.toString()
458
+ )
459
+ ),
460
+ new cs.Literal(i),
461
+ false
462
+ ),
463
+ cs.AnnotatedStatement.getPropertyList({
464
+ Value: new cs.Literal(enumValue),
465
+ })
466
+ )
467
+ )
468
+ .map((s) => new cs.StatementBlock([s]))
469
+ )
470
+
471
+ const enumDef =
472
+ ty === "string"
473
+ ? new cs.AnnotatedStatement("JsonConverter", enumNode, [
474
+ new cs.TokenNodeApplyFunction(new cs.TokenNode("typeof"), [
475
+ new cs.TokenNode("StringEnumConverter"),
476
+ ]),
477
+ ])
478
+ : enumNode
479
+
480
+ const typeNode = new cs.TypeNode(
481
+ root_name
482
+ ? new cs.AccessChain([
483
+ new cs.TokenNode(root_name),
484
+ new cs.TokenNode(enumName),
485
+ ])
486
+ : new cs.TokenNode(enumName),
487
+ nullable
488
+ )
489
+
490
+ return {
491
+ enumDef,
492
+ typeNode,
493
+ enumName,
494
+ }
495
+
496
+ function safeWrapEnumValue(value: string) {
497
+ if (!value) {
498
+ return `empty`
499
+ }
500
+
501
+ const code = value.charCodeAt(0)
502
+
503
+ const is_alpha =
504
+ (code > 64 && code < 91) || // upper alpha (A-Z)
505
+ (code > 96 && code < 123) // lower alpha (a-z)
506
+
507
+ if (!is_alpha) {
508
+ return "_" + value
509
+ }
510
+
511
+ return value
512
+ }
513
+ }
514
+
515
+ const generateDataclassesForObjectOrRefSchema = (
516
+ name: string,
517
+ schema: ObjSchema | RefSchema,
518
+ resource_type: "response" | "request" | "model",
519
+ namespace?: string[],
520
+ topLevelOptions: {
521
+ enumOverrides?: Record<string, cs.CSharpNode>
522
+ base?: cs.TokenNode
523
+ } = {},
524
+ persistentOptions: {
525
+ forceNullable?: boolean
526
+ } = {}
527
+ ) => {
528
+ const { enumOverrides: topLevelEnumOverrides, base } = topLevelOptions
529
+
530
+ const { forceNullable = false } = persistentOptions
531
+
532
+ const extraFields = new Map<string, cs.Statement>()
533
+ const extraClasses: cs.AnnotatedStatement<cs.Class>[] = []
534
+
535
+ const required = "required" in schema ? new Set(schema.required) : new Set()
536
+ const properties =
537
+ "properties" in schema ? Object.entries(schema.properties) : []
538
+
539
+ const isSchemaObjectRecursive = (schema: PropertySchema[]): boolean => {
540
+ return schema.every(
541
+ (s) =>
542
+ ("type" in s && s.type === "object") ||
543
+ ("allOf" in s && isSchemaObjectRecursive(s.allOf)) ||
544
+ ("oneOf" in s && isSchemaObjectRecursive(s.oneOf))
545
+ )
546
+ }
547
+
548
+ const mapSchemaEnum = (
549
+ property_name: string,
550
+ nullable: boolean,
551
+ enumValues: (string | number)[],
552
+ ty: "number" | "string"
553
+ ) => {
554
+ const { enumDef, enumName, typeNode } = generateEnumDefs(
555
+ property_name,
556
+ nullable,
557
+ enumValues,
558
+ ty,
559
+ name
560
+ )
561
+
562
+ extraFields.set(enumName, enumDef)
563
+
564
+ return typeNode
565
+ }
566
+
567
+ const mapOneOfType = (
568
+ schema: OneOfSchema,
569
+ property_name: string,
570
+ nullable: boolean
571
+ ): cs.TypeNode => {
572
+ if (!schema.discriminator) {
573
+ if (schema.oneOf.every((s) => "type" in s && s.type === "string")) {
574
+ // TODO: support union over date-time, uri, uuid
575
+ return new cs.TypeNode(cs.TokenNode.TYPE_STRING, nullable)
576
+ }
577
+
578
+ console.warn(`OneOf not supported for ${name}, ${property_name}`)
579
+
580
+ if (isSchemaObjectRecursive(schema.oneOf)) {
581
+ return new cs.TypeNode(cs.TokenNode.TYPE_JOBJECT, nullable)
582
+ }
583
+
584
+ return FALLBACK_TYPE
585
+ }
586
+
587
+ const { classDefs, className } = generateDataclassesForOneOfSchema(
588
+ property_name,
589
+ schema,
590
+ resource_type,
591
+ namespace
592
+ )
593
+
594
+ extraFields.set(className, new cs.StatementBlock(classDefs))
595
+
596
+ return new cs.TypeNode(new cs.TokenNode(className), nullable)
597
+ }
598
+
599
+ const mapAllOfType = (
600
+ schema: AllOfSchema,
601
+ property_name: string,
602
+ nullable: boolean
603
+ ): cs.TypeNode => {
604
+ const flattened = deepFlattenAllOfSchema(schema)
605
+ if (flattened != null) {
606
+ return mapSchemaType(flattened, property_name, nullable)
607
+ }
608
+
609
+ console.warn(`AllOf not supported for ${name}, ${property_name}`)
610
+
611
+ if (isSchemaObjectRecursive(schema.allOf)) {
612
+ return new cs.TypeNode(cs.TokenNode.TYPE_JOBJECT, nullable)
613
+ }
614
+
615
+ return FALLBACK_TYPE
616
+ }
617
+
618
+ const mapSchemaType = (
619
+ schema: PropertySchema,
620
+ property_name: string,
621
+ nullable: boolean
622
+ ): cs.TypeNode => {
623
+ if ("$ref" in schema) {
624
+ return new cs.TypeNode(new cs.TokenNode(schema.$ref), nullable)
625
+ }
626
+
627
+ if ("oneOf" in schema) {
628
+ if (
629
+ schema.oneOf.every((s) => "type" in s && s.type === "string" && s.enum)
630
+ ) {
631
+ schema = {
632
+ type: "string",
633
+ enum: schema.oneOf.flatMap((s) => {
634
+ assert("type" in s)
635
+
636
+ if (s.type !== "string") return []
637
+ return s.enum ?? []
638
+ }),
639
+ ...schema,
640
+ }
641
+ } else {
642
+ return mapOneOfType(schema, property_name, nullable)
643
+ }
644
+ }
645
+
646
+ if ("allOf" in schema) {
647
+ return mapAllOfType(schema, property_name, nullable)
648
+ }
649
+
650
+ switch (schema.type) {
651
+ case "string": {
652
+ if (schema.enum && !topLevelEnumOverrides?.[property_name]) {
653
+ return mapSchemaEnum(property_name, nullable, schema.enum, "string")
654
+ }
655
+
656
+ return new cs.TypeNode(cs.TokenNode.TYPE_STRING, nullable)
657
+ }
658
+ case "integer":
659
+ if (schema.enum) {
660
+ return mapSchemaEnum(property_name, nullable, schema.enum, "number")
661
+ }
662
+
663
+ return new cs.TypeNode(cs.TokenNode.TYPE_INT, nullable)
664
+ case "boolean":
665
+ return new cs.TypeNode(cs.TokenNode.TYPE_BOOLEAN, nullable)
666
+ case "object":
667
+ if ("additionalProperties" in schema) {
668
+ // TODO: support enums
669
+ return FALLBACK_TYPE
670
+ }
671
+
672
+ const newClassName = pascalCase(name + pascalCase(property_name))
673
+
674
+ const newClasses = generateDataclassesForObjectOrRefSchema(
675
+ newClassName,
676
+ schema,
677
+ "model",
678
+ namespace,
679
+ {},
680
+ {
681
+ ...persistentOptions,
682
+ ...(newClassName === "DeviceProperties" && {
683
+ forceNullable: true,
684
+ }),
685
+ }
686
+ )
687
+
688
+ extraClasses.push(...newClasses.classDefs)
689
+
690
+ return new cs.TypeNode(new cs.TokenNode(newClassName), nullable)
691
+ case "array":
692
+ return new cs.TypeNode(
693
+ new cs.TokenNodeGeneric("List", [
694
+ mapSchemaType(
695
+ schema.items,
696
+ property_name,
697
+ "nullable" in schema.items ? !!schema.items.nullable : false
698
+ ),
699
+ ]),
700
+ nullable
701
+ )
702
+ case "number":
703
+ return new cs.TypeNode(cs.TokenNode.TYPE_FLOAT, nullable)
704
+ default:
705
+ console.warn(
706
+ `Unknown type for class ${name}, property ${property_name} ${JSON.stringify(
707
+ schema,
708
+ null,
709
+ 2
710
+ )}`
711
+ )
712
+
713
+ return new cs.TypeNode(cs.TokenNode.TYPE_OBJECT_CLASS)
714
+ }
715
+ }
716
+
717
+ const mapTypeToProperty = ([property_name, schema]: [
718
+ property_name: string,
719
+ schema: PropertySchema,
720
+ ]) => {
721
+ const isRequired =
722
+ required.has(property_name) &&
723
+ !("nullable" in schema && schema.nullable) &&
724
+ !forceNullable
725
+
726
+ const enumOverride = topLevelEnumOverrides?.[property_name]
727
+
728
+ return new cs.AnnotatedStatement(
729
+ "DataMember",
730
+ new cs.PropertyDeclaration(
731
+ mapSchemaType(
732
+ schema,
733
+ property_name,
734
+ forceNullable ||
735
+ ("nullable" in schema ? !!schema.nullable : !isRequired)
736
+ ),
737
+ new cs.TokenNode(pascalCase(property_name)),
738
+ new cs.PropertyMethods({}, enumOverride ? undefined : {}),
739
+ new cs.VisibilityModifiers([
740
+ "public",
741
+ ...(enumOverride ? ["override" as const] : []),
742
+ ]),
743
+ enumOverride
744
+ ),
745
+ cs.AnnotatedStatement.getPropertyList({
746
+ Name: new cs.Literal(snakeCase(property_name)),
747
+ IsRequired: new cs.Literal(isRequired),
748
+ EmitDefaultValue: new cs.Literal(false),
749
+ })
750
+ )
751
+ }
752
+
753
+ const classNameToken = new cs.TokenNode(pascalCase(name))
754
+
755
+ const jsonConstructor = new cs.AnnotatedStatement(
756
+ "JsonConstructorAttribute",
757
+ new cs.MethodDeclaration(
758
+ undefined,
759
+ new cs.MethodNode(classNameToken, []),
760
+ new cs.CurlyBlock([]),
761
+ new cs.VisibilityModifiers([
762
+ properties.length > 0 ? "protected" : "public",
763
+ ])
764
+ )
765
+ )
766
+
767
+ if (pascalCase(name) === "ActionAttempt") {
768
+ console.log("action_attempt", { status_properties: properties[0]?.[1] })
769
+ }
770
+
771
+ const propertyDefs = properties.map(mapTypeToProperty)
772
+
773
+ const parameterDefs = propertyDefs.map((pd) => {
774
+ if (!pd.annotated.type)
775
+ throw new Error(`No type for property def ${pd.annotated.token.token}`)
776
+
777
+ return new cs.ParameterNode(
778
+ pd.annotated.type,
779
+ new cs.TokenNode(camelCase(pd.annotated.token.token)),
780
+ new cs.TokenNode("default")
781
+ )
782
+ })
783
+
784
+ const constructors: cs.Statement[] = [jsonConstructor]
785
+
786
+ if (propertyDefs.length > 0) {
787
+ const publicConstructor = new cs.MethodDeclaration(
788
+ undefined,
789
+ new cs.MethodNode(classNameToken, parameterDefs),
790
+ new cs.CurlyBlock([
791
+ new cs.StatementBlock(
792
+ propertyDefs.map(
793
+ (pd) =>
794
+ // FIXME: do non-null assertions here
795
+ new cs.AssignStatement(
796
+ new cs.TokenNode(pascalCase(pd.annotated.token.token)),
797
+ new cs.TokenNode(camelCase(pd.annotated.token.token))
798
+ )
799
+ )
800
+ ),
801
+ ]),
802
+ new cs.VisibilityModifiers(["public"])
803
+ )
804
+
805
+ constructors.push(publicConstructor)
806
+ }
807
+
808
+ const toStringMethod = getToStringMethod(classNameToken.token, properties)
809
+
810
+ const data_contract_name = [
811
+ ...(namespace && namespace.length > 0
812
+ ? [camelCase(namespace.join("_"))]
813
+ : []),
814
+ camelCase(name),
815
+ resource_type,
816
+ ].join("_")
817
+
818
+ const classDefs = [
819
+ new cs.AnnotatedStatement(
820
+ "DataContract",
821
+ new cs.Class(
822
+ new cs.ClassDeclarationSpecifier(
823
+ classNameToken,
824
+ base?.token,
825
+ new cs.VisibilityModifiers(["public"])
826
+ ),
827
+
828
+ [
829
+ ...constructors,
830
+ ...extraFields.values(),
831
+ ...propertyDefs,
832
+ toStringMethod,
833
+ ].map((pd) => new cs.StatementBlock([pd]))
834
+ ),
835
+ cs.AnnotatedStatement.getPropertyList({
836
+ Name: new cs.Literal(data_contract_name),
837
+ })
838
+ ),
839
+ ...extraClasses,
840
+ ]
841
+
842
+ return {
843
+ className: name,
844
+ classDefs,
845
+ parameterDefs,
846
+ propertyDefs,
847
+ } satisfies GeneratedDataclassResult
848
+ }
849
+
850
+ const generateDataclassesForOneOfSchema = (
851
+ name: string,
852
+ schema: OneOfSchema,
853
+ resource_type: "response" | "request" | "model",
854
+ namespace?: string[]
855
+ ): GeneratedDataclassResult => {
856
+ if (!schema.discriminator) {
857
+ throw new Error(
858
+ "OneOfSchema must have discriminator: " + JSON.stringify(schema, null, 2)
859
+ )
860
+ }
861
+
862
+ const { propertyName: discriminatedPropertyName } = schema.discriminator
863
+
864
+ const objSchemas = schema.oneOf.map((s) => {
865
+ if (!("type" in s && s.type === "object")) {
866
+ throw new Error("OneOfSchema must have object types")
867
+ }
868
+
869
+ const prop = s.properties[discriminatedPropertyName]
870
+
871
+ if (
872
+ !(
873
+ prop &&
874
+ "type" in prop &&
875
+ prop.type === "string" &&
876
+ prop.enum &&
877
+ prop.enum.length === 1
878
+ )
879
+ ) {
880
+ throw new Error(
881
+ "OneOfSchema must have string discriminator: " +
882
+ JSON.stringify(schema, null, 2)
883
+ )
884
+ }
885
+
886
+ const specificName = prop.enum[0]!
887
+
888
+ return [specificName, s] as const
889
+ })
890
+
891
+ const defs: cs.Statement[] = []
892
+
893
+ const specifiedClassDefs: cs.Statement[] = []
894
+ const specifiedClassNames: [string, string][] = []
895
+
896
+ const propertyDeclaration = new cs.PropertyDeclaration(
897
+ new cs.TypeNode(cs.TokenNode.TYPE_STRING),
898
+ new cs.TokenNode(pascalCase(discriminatedPropertyName)),
899
+ new cs.PropertyMethods({}, undefined),
900
+ new cs.VisibilityModifiers(["public", "abstract"])
901
+ )
902
+
903
+ const toStringDeclaration = new cs.MethodDeclaration(
904
+ new cs.TypeNode(new cs.TokenNode("string")),
905
+ new cs.MethodNode(new cs.TokenNode("ToString"), []),
906
+ undefined,
907
+ new cs.VisibilityModifiers(["public", "abstract", "override"])
908
+ )
909
+
910
+ defs.push(propertyDeclaration, toStringDeclaration)
911
+
912
+ const classNameToken = new cs.TokenNode(pascalCase(name))
913
+
914
+ for (const [specifiedName, subschema] of objSchemas) {
915
+ const specifiedClassName = pascalCase(name) + pascalCase(specifiedName)
916
+
917
+ const { classDefs } = generateDataclassesForObjectOrRefSchema(
918
+ specifiedClassName,
919
+ subschema,
920
+ resource_type,
921
+ namespace,
922
+ {
923
+ enumOverrides: {
924
+ [discriminatedPropertyName]: new cs.Literal(specifiedName),
925
+ },
926
+ base: classNameToken,
927
+ }
928
+ )
929
+
930
+ specifiedClassDefs.push(...classDefs)
931
+ specifiedClassNames.push([specifiedClassName, specifiedName])
932
+ }
933
+
934
+ const classDef = new cs.Class(
935
+ new cs.ClassDeclarationSpecifier(
936
+ classNameToken,
937
+ undefined,
938
+ new cs.VisibilityModifiers(["public", "abstract"])
939
+ ),
940
+ defs.map((d) => new cs.StatementBlock([d]))
941
+ )
942
+
943
+ let wrappedClassDef: cs.Statement = classDef
944
+
945
+ for (const [specifiedClassName, specifiedName] of specifiedClassNames) {
946
+ wrappedClassDef = new cs.AnnotatedStatement(
947
+ "JsonSubtypes.KnownSubType",
948
+ wrappedClassDef,
949
+ [
950
+ new cs.TokenNodeApplyFunction(new cs.TokenNode("typeof"), [
951
+ new cs.TokenNode(specifiedClassName),
952
+ ]),
953
+ new cs.Literal(snakeCase(specifiedName)),
954
+ ]
955
+ )
956
+ }
957
+
958
+ const withJsonConverter = new cs.AnnotatedStatement(
959
+ "JsonConverter",
960
+ wrappedClassDef,
961
+ [
962
+ new cs.TokenNodeApplyFunction(new cs.TokenNode("typeof"), [
963
+ new cs.TokenNode("JsonSubtypes"),
964
+ ]),
965
+ new cs.Literal(pascalCase(discriminatedPropertyName)),
966
+ ]
967
+ )
968
+
969
+ return {
970
+ className: classNameToken.token,
971
+ classDefs: [withJsonConverter, ...specifiedClassDefs],
972
+ }
973
+ }