@aws/nx-plugin 1.0.0-rc.32 → 1.0.0-rc.34

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 (277) hide show
  1. package/LICENSE-THIRD-PARTY +75 -86
  2. package/generators.json +27 -0
  3. package/package.json +10 -10
  4. package/src/connection/generator.js +12 -1
  5. package/src/connection/generator.js.map +1 -1
  6. package/src/connection/supported-connections.d.ts +10 -1
  7. package/src/connection/supported-connections.js +13 -0
  8. package/src/connection/supported-connections.js.map +1 -1
  9. package/src/infra/app/__snapshots__/generator.spec.ts.snap +21 -21
  10. package/src/infra/app/files/app/src/main.ts.template +1 -1
  11. package/src/infra/app/files/app/src/stages/application-stage.ts.template +1 -1
  12. package/src/infra/app/generator.js +3 -1
  13. package/src/infra/app/generator.js.map +1 -1
  14. package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +12 -12
  15. package/src/open-api/ts-client/__snapshots__/generator.composite-types.spec.ts.snap +74 -10
  16. package/src/open-api/ts-client/__snapshots__/generator.content-type.spec.ts.snap +22 -4
  17. package/src/open-api/ts-client/__snapshots__/generator.duplicate-types.spec.ts.snap +53 -8
  18. package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +32 -4
  19. package/src/open-api/ts-client/__snapshots__/generator.fast-api-gaps.spec.ts.snap +736 -0
  20. package/src/open-api/ts-client/__snapshots__/generator.fast-api.spec.ts.snap +86 -11
  21. package/src/open-api/ts-client/__snapshots__/generator.multipart.spec.ts.snap +21 -3
  22. package/src/open-api/ts-client/__snapshots__/generator.primitive-types.spec.ts.snap +2 -2
  23. package/src/open-api/ts-client/__snapshots__/generator.request.spec.ts.snap +6 -6
  24. package/src/open-api/ts-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +2 -2
  25. package/src/open-api/ts-client/__snapshots__/generator.spec-compliance.spec.ts.snap +1883 -0
  26. package/src/open-api/ts-client/__snapshots__/generator.tags.spec.ts.snap +4 -4
  27. package/src/open-api/ts-client/files/client.gen.ts.template +196 -13
  28. package/src/open-api/ts-client/files/types.gen.ts.template +2 -0
  29. package/src/open-api/ts-client/generator.js +27 -2
  30. package/src/open-api/ts-client/generator.js.map +1 -1
  31. package/src/open-api/ts-hooks/files/options-proxy.gen.ts.template +2 -2
  32. package/src/open-api/ts-hooks/generator.js +5 -1
  33. package/src/open-api/ts-hooks/generator.js.map +1 -1
  34. package/src/open-api/utils/codegen-data/languages.js +6 -0
  35. package/src/open-api/utils/codegen-data/languages.js.map +1 -1
  36. package/src/open-api/utils/codegen-data/types.d.ts +16 -1
  37. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  38. package/src/open-api/utils/codegen-data.js +71 -0
  39. package/src/open-api/utils/codegen-data.js.map +1 -1
  40. package/src/open-api/utils/normalise.js +53 -8
  41. package/src/open-api/utils/normalise.js.map +1 -1
  42. package/src/open-api/utils/parser.js +48 -15
  43. package/src/open-api/utils/parser.js.map +1 -1
  44. package/src/preset/__snapshots__/generator.spec.ts.snap +5 -3
  45. package/src/preset/generator.d.ts +1 -1
  46. package/src/preset/generator.js +5 -2
  47. package/src/preset/generator.js.map +1 -1
  48. package/src/preset/schema.d.js.map +1 -1
  49. package/src/preset/schema.d.ts +2 -0
  50. package/src/preset/schema.json +6 -0
  51. package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +7 -7
  52. package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +8 -8
  53. package/src/py/agent/__snapshots__/generator.protocols.spec.ts.snap +89 -3
  54. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
  55. package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +12 -12
  56. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
  57. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +91 -5
  58. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2038 -0
  59. package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +104 -0
  60. package/src/py/rdb/agent-connection/generator.d.ts +10 -0
  61. package/src/py/rdb/agent-connection/generator.js +46 -0
  62. package/src/py/rdb/agent-connection/generator.js.map +1 -0
  63. package/src/py/rdb/agent-connection/schema.d.js +8 -0
  64. package/src/py/rdb/agent-connection/schema.d.js.map +1 -0
  65. package/src/py/rdb/agent-connection/schema.d.ts +15 -0
  66. package/src/py/rdb/agent-connection/schema.json +27 -0
  67. package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +44 -0
  68. package/src/py/rdb/fast-api-connection/files/__apiModuleName__/dependencies/__rdbNameSnake__.py.template +14 -0
  69. package/src/py/rdb/fast-api-connection/generator.d.ts +10 -0
  70. package/src/py/rdb/fast-api-connection/generator.js +54 -0
  71. package/src/py/rdb/fast-api-connection/generator.js.map +1 -0
  72. package/src/py/rdb/fast-api-connection/schema.d.js +8 -0
  73. package/src/py/rdb/fast-api-connection/schema.d.js.map +1 -0
  74. package/src/py/rdb/fast-api-connection/schema.d.ts +13 -0
  75. package/src/py/rdb/fast-api-connection/schema.json +23 -0
  76. package/src/py/rdb/files/Dockerfile.create-db-user.template +10 -0
  77. package/src/py/rdb/files/Dockerfile.migration.template +10 -0
  78. package/src/py/rdb/files/__name__/__init__.py.template +3 -0
  79. package/src/py/rdb/files/__name__/connection.py.template +55 -0
  80. package/src/py/rdb/files/__name__/create_db_user_handler.py.template +97 -0
  81. package/src/py/rdb/files/__name__/migration_handler.py.template +36 -0
  82. package/src/py/rdb/files/__name__/models/__init__.py.template +3 -0
  83. package/src/py/rdb/files/__name__/models/example.py.template +8 -0
  84. package/src/py/rdb/files/__name__/utils.py.template +104 -0
  85. package/src/py/rdb/files/alembic.ini.template +38 -0
  86. package/src/py/rdb/files/config.json.template +14 -0
  87. package/src/py/rdb/files/migrations/env.py.template +80 -0
  88. package/src/py/rdb/files/migrations/script.py.mako.template +28 -0
  89. package/src/py/rdb/generator.d.ts +6 -0
  90. package/src/py/rdb/generator.js +263 -0
  91. package/src/py/rdb/generator.js.map +1 -0
  92. package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +101 -0
  93. package/src/py/rdb/mcp-server-connection/generator.d.ts +10 -0
  94. package/src/py/rdb/mcp-server-connection/generator.js +46 -0
  95. package/src/py/rdb/mcp-server-connection/generator.js.map +1 -0
  96. package/src/py/rdb/mcp-server-connection/schema.d.js +8 -0
  97. package/src/py/rdb/mcp-server-connection/schema.d.js.map +1 -0
  98. package/src/py/rdb/mcp-server-connection/schema.d.ts +15 -0
  99. package/src/py/rdb/mcp-server-connection/schema.json +27 -0
  100. package/src/py/rdb/schema.d.js +6 -0
  101. package/src/py/rdb/schema.d.js.map +1 -0
  102. package/src/py/rdb/schema.d.ts +16 -0
  103. package/src/py/rdb/schema.json +77 -0
  104. package/src/py/rdb/utils.d.ts +6 -0
  105. package/src/py/rdb/utils.js +16 -0
  106. package/src/py/rdb/utils.js.map +1 -0
  107. package/src/sdk/py.d.ts +2 -0
  108. package/src/sdk/py.js +1 -0
  109. package/src/sdk/py.js.map +1 -1
  110. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +7 -7
  111. package/src/smithy/ts/api/files/handler.ts.template +2 -2
  112. package/src/smithy/ts/api/files/local-server.ts.template +2 -2
  113. package/src/smithy/ts/api/files/operations/echo.ts.template +2 -2
  114. package/src/smithy/ts/api/files/service.ts.template +3 -3
  115. package/src/smithy/ts/api/generator.js +3 -1
  116. package/src/smithy/ts/api/generator.js.map +1 -1
  117. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +12 -12
  118. package/src/trpc/backend/files/src/client/index.ts.template +1 -1
  119. package/src/trpc/backend/files/src/handler.ts.template +1 -1
  120. package/src/trpc/backend/files/src/index.ts.template +5 -5
  121. package/src/trpc/backend/files/src/init.ts.template +1 -1
  122. package/src/trpc/backend/files/src/local-server.ts.template +1 -1
  123. package/src/trpc/backend/files/src/middleware/index.ts.template +7 -7
  124. package/src/trpc/backend/files/src/procedures/echo.ts.template +2 -2
  125. package/src/trpc/backend/files/src/router.ts.template +2 -2
  126. package/src/trpc/backend/files/src/schema/index.ts.template +1 -1
  127. package/src/trpc/backend/generator.js +3 -1
  128. package/src/trpc/backend/generator.js.map +1 -1
  129. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +89 -3
  130. package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client-strands.ts.template +2 -2
  131. package/src/ts/agent/a2a-connection/generator.js +3 -1
  132. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  133. package/src/ts/agent/files/a2a/index.ts.template +1 -1
  134. package/src/ts/agent/files/ag-ui/index.ts.template +1 -1
  135. package/src/ts/agent/files/http/client.ts.template +2 -2
  136. package/src/ts/agent/files/http/index.ts.template +2 -2
  137. package/src/ts/agent/files/http/router.ts.template +3 -3
  138. package/src/ts/agent/gateway-connection/files/agent-connection/app/__gatewayKebabCase__-client-strands.ts.template +2 -2
  139. package/src/ts/agent/gateway-connection/generator.js +3 -1
  140. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  141. package/src/ts/agent/generator.js +5 -2
  142. package/src/ts/agent/generator.js.map +1 -1
  143. package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client-strands.ts.template +2 -2
  144. package/src/ts/agent/mcp-connection/generator.js +3 -1
  145. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  146. package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +3 -2
  147. package/src/ts/astro-docs/generator.js +2 -0
  148. package/src/ts/astro-docs/generator.js.map +1 -1
  149. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
  150. package/src/ts/dynamodb/files/src/client.ts.template +5 -2
  151. package/src/ts/dynamodb/files/src/entities/example.ts.template +1 -1
  152. package/src/ts/dynamodb/files/src/entities/index.ts.template +1 -1
  153. package/src/ts/dynamodb/files/src/index.ts.template +2 -2
  154. package/src/ts/dynamodb/generator.js +3 -1
  155. package/src/ts/dynamodb/generator.js.map +1 -1
  156. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
  157. package/src/ts/lib/generator.js +7 -1
  158. package/src/ts/lib/generator.js.map +1 -1
  159. package/src/ts/lib/ts-project-utils.js +19 -4
  160. package/src/ts/lib/ts-project-utils.js.map +1 -1
  161. package/src/ts/lib/types.d.ts +6 -0
  162. package/src/ts/lib/types.js.map +1 -1
  163. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +94 -8
  164. package/src/ts/mcp-server/generator.js +3 -2
  165. package/src/ts/mcp-server/generator.js.map +1 -1
  166. package/src/ts/nx-generator/files/local/generator.ts.template +2 -2
  167. package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.ts.template +2 -2
  168. package/src/ts/nx-generator/generator.js +5 -2
  169. package/src/ts/nx-generator/generator.js.map +1 -1
  170. package/src/ts/nx-plugin/files/mcp-server/server.ts.template +5 -5
  171. package/src/ts/nx-plugin/files/mcp-server/tools/create-workspace-command.ts.template +2 -2
  172. package/src/ts/nx-plugin/files/mcp-server/tools/general-guidance.ts.template +1 -1
  173. package/src/ts/nx-plugin/files/mcp-server/tools/generator-guide.ts.template +2 -2
  174. package/src/ts/nx-plugin/files/mcp-server/tools/list-generators.ts.template +2 -2
  175. package/src/ts/nx-plugin/files/mcp-server/utils.ts.template +3 -3
  176. package/src/ts/nx-plugin/generator.js +3 -1
  177. package/src/ts/nx-plugin/generator.js.map +1 -1
  178. package/src/ts/nx-plugin/utils.js +7 -4
  179. package/src/ts/nx-plugin/utils.js.map +1 -1
  180. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +149 -177
  181. package/src/ts/rdb/files/src/create-db-user-handler.ts.template +2 -2
  182. package/src/ts/rdb/files/src/index.ts.template +1 -1
  183. package/src/ts/rdb/files/src/migration-handler.ts.template +1 -1
  184. package/src/ts/rdb/files/src/prisma.ts.template +7 -4
  185. package/src/ts/rdb/generator.js +7 -4
  186. package/src/ts/rdb/generator.js.map +1 -1
  187. package/src/ts/rdb/schema.json +1 -1
  188. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +45 -45
  189. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +2 -2
  190. package/src/utils/agent-chat/agent-chat.js +3 -1
  191. package/src/utils/agent-chat/agent-chat.js.map +1 -1
  192. package/src/utils/agent-chat/files/a2a/chat.ts.template +1 -1
  193. package/src/utils/agent-chat/files/ag-ui/chat.ts.template +1 -1
  194. package/src/utils/agent-chat/files/http-py/chat.ts.template +2 -2
  195. package/src/utils/agent-chat/files/http-ts/chat.ts.template +1 -1
  196. package/src/utils/agent-connection/agent-connection.js +4 -1
  197. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  198. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +2 -2
  199. package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +1 -1
  200. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +2 -2
  201. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +2 -2
  202. package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +1 -1
  203. package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +1 -1
  204. package/src/utils/agent-connection/files/core-strands/base/with-session-id-strands.ts.template +1 -1
  205. package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +1 -1
  206. package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +1 -1
  207. package/src/utils/agent-core-constructs/agent-core-constructs.js +10 -3
  208. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  209. package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +3 -3
  210. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +4 -4
  211. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +1 -1
  212. package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +27 -0
  213. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +60 -1
  214. package/src/utils/api-constructs/api-constructs.js +8 -2
  215. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  216. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +8 -8
  217. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +8 -8
  218. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +3 -3
  219. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account/index.js.template +32 -20
  220. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +1 -1
  221. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +4 -4
  222. package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +1 -1
  223. package/src/utils/ast.js +16 -0
  224. package/src/utils/ast.js.map +1 -1
  225. package/src/utils/commands.d.ts +1 -1
  226. package/src/utils/commands.js +4 -1
  227. package/src/utils/commands.js.map +1 -1
  228. package/src/utils/dynamodb-constructs/dynamodb-constructs.js +9 -2
  229. package/src/utils/dynamodb-constructs/dynamodb-constructs.js.map +1 -1
  230. package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +3 -3
  231. package/src/utils/dynamodb-constructs/files/cdk/core/dynamodb.ts.template +1 -1
  232. package/src/utils/files/common/constructs/src/core/index.ts.template +4 -4
  233. package/src/utils/files/common/constructs/src/index.ts.template +2 -2
  234. package/src/utils/files/common/infra-config/src/index.ts.template +3 -3
  235. package/src/utils/files/common/infra-config/src/resolve-stage.ts.template +2 -2
  236. package/src/utils/files/common/infra-config/src/stages.config.ts.template +1 -1
  237. package/src/utils/files/common/scripts/src/infra/infra-deploy.ts.template +1 -1
  238. package/src/utils/files/common/scripts/src/infra/infra-destroy.ts.template +1 -1
  239. package/src/utils/files/common/scripts/src/infra/stage-credentials/run.ts.template +3 -3
  240. package/src/utils/files/common/shadcn/src/index.ts.template +2 -2
  241. package/src/utils/function-constructs/files/cdk/app/lambda-functions/__nameKebabCase__.ts.template +1 -1
  242. package/src/utils/function-constructs/function-constructs.js +3 -1
  243. package/src/utils/function-constructs/function-constructs.js.map +1 -1
  244. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +2 -2
  245. package/src/utils/identity-constructs/identity-constructs.js +5 -1
  246. package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
  247. package/src/utils/module-format.d.ts +28 -0
  248. package/src/utils/module-format.js +28 -0
  249. package/src/utils/module-format.js.map +1 -0
  250. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +61 -17
  251. package/src/utils/rdb-constructs/files/cdk/core/rdb/aurora.ts.template +68 -78
  252. package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +88 -8
  253. package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +5 -32
  254. package/src/utils/rdb-constructs/rdb-constructs.d.ts +11 -1
  255. package/src/utils/rdb-constructs/rdb-constructs.js +9 -2
  256. package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
  257. package/src/utils/shared-constructs.js +12 -22
  258. package/src/utils/shared-constructs.js.map +1 -1
  259. package/src/utils/shared-infra-config.js +3 -1
  260. package/src/utils/shared-infra-config.js.map +1 -1
  261. package/src/utils/shared-infra-scripts.js +3 -1
  262. package/src/utils/shared-infra-scripts.js.map +1 -1
  263. package/src/utils/shared-rdb-scripts.js +5 -1
  264. package/src/utils/shared-rdb-scripts.js.map +1 -1
  265. package/src/utils/shared-shadcn.js +3 -1
  266. package/src/utils/shared-shadcn.js.map +1 -1
  267. package/src/utils/test.d.ts +2 -0
  268. package/src/utils/test.js +7 -1
  269. package/src/utils/test.js.map +1 -1
  270. package/src/utils/versions.d.ts +73 -69
  271. package/src/utils/versions.js +71 -67
  272. package/src/utils/versions.js.map +1 -1
  273. package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +2 -2
  274. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +2 -2
  275. package/src/utils/website-constructs/website-constructs.js +9 -2
  276. package/src/utils/website-constructs/website-constructs.js.map +1 -1
  277. package/src/utils/files/terraform/scripts/reset-runtime-config.ts.template +0 -25
@@ -579,7 +579,7 @@ export class TestApi {
579
579
  );
580
580
 
581
581
  if (response.status === 201) {
582
- return await response.text();
582
+ return await response.json();
583
583
  }
584
584
  throw new Error(
585
585
  \`Unknown response status \${response.status} returned by API\`,
@@ -630,7 +630,7 @@ export class TestApi {
630
630
  );
631
631
 
632
632
  if (response.status === 200) {
633
- return await response.text();
633
+ return await response.json();
634
634
  }
635
635
  throw new Error(
636
636
  \`Unknown response status \${response.status} returned by API\`,
@@ -837,7 +837,7 @@ export class TestApi {
837
837
  );
838
838
 
839
839
  if (response.status === 200) {
840
- return await response.text();
840
+ return await response.json();
841
841
  }
842
842
  throw new Error(
843
843
  \`Unknown response status \${response.status} returned by API\`,
@@ -861,7 +861,7 @@ export class TestApi {
861
861
  );
862
862
 
863
863
  if (response.status === 200) {
864
- return Number(await response.text());
864
+ return await response.json();
865
865
  }
866
866
  throw new Error(
867
867
  \`Unknown response status \${response.status} returned by API\`,
@@ -29,6 +29,19 @@ const composedMarshaller = (property, method) =>
29
29
  property.export === 'reference' && discriminatorBaseNames.has(property.type)
30
30
  ? `$IO.${property.typescriptType}.$${method}Base`
31
31
  : `$IO.${property.typescriptType}.${method}`;
32
+ // Names of object models composed by a non-discriminated one-of/any-of. These
33
+ // additionally emit an internal `$fromJsonPartial` marshaller that converts
34
+ // only the properties present on the wire value, so composing the union's
35
+ // members never fabricates values (e.g. an Invalid Date) from a non-matching
36
+ // member's absent required fields. Discriminated unions dispatch to a single
37
+ // member instead and never compose, so they don't need the partial form.
38
+ const unionMemberNames = new Set(models
39
+ .filter(m => (m.export === 'one-of' || m.export === 'any-of') && !m.discriminator)
40
+ .flatMap(m => (m.composedModels || []).map(c => c.name)));
41
+ const hasPartialMarshaller = (name) => {
42
+ const member = unionMemberNames.has(name) && modelByName[name];
43
+ return member && !['one-of', 'any-of', 'all-of', 'dictionary', 'enum', 'tuple'].includes(member.export);
44
+ };
32
45
  // The single wire media type chosen for an operation's request body, if any.
33
46
  const bodyMediaTypeOf = (op) => {
34
47
  if (!op.parametersBody || !op.parametersBody.mediaTypes) return undefined;
@@ -36,6 +49,14 @@ const bodyMediaTypeOf = (op) => {
36
49
  return mediaTypes.find(mt => mt === 'application/json' || mt.endsWith('+json')) || mediaTypes[0];
37
50
  };
38
51
  const hasMultipartBody = allOperations.some(op => bodyMediaTypeOf(op) === 'multipart/form-data');
52
+ const hasUrlEncodedBody = allOperations.some(op => bodyMediaTypeOf(op) === 'application/x-www-form-urlencoded');
53
+ // Whether any operation uses matrix/label path styles or allowReserved query
54
+ // params, so the extra $url serialisation logic is only emitted when needed.
55
+ const hasStyledPathParams = allOperations.some(op => (op.parameters || []).some(p => p.in === 'path' && p.pathStyle));
56
+ const hasAllowReservedParams = allOperations.some(op => (op.parameters || []).some(p => p.in === 'query' && p.allowReserved));
57
+ // Whether a response is JSON on the wire (so primitives arrive JSON-encoded,
58
+ // e.g. a string response body is `"hello"` including the quotes).
59
+ const isJsonResponse = (response) => (response.mediaTypes || []).some(mt => mt === 'application/json' || mt.split(';')[0].endsWith('+json'));
39
60
  _%>
40
61
  <%_ if ((models.length + allOperations.filter(p => p.parameters.length > 0).length) > 0) { _%>
41
62
  import type {
@@ -45,7 +66,7 @@ import type {
45
66
  <%_ allOperations.filter(p => p.parameters.length > 0).forEach((op) => { _%>
46
67
  <%- op.requestTypeName %>,
47
68
  <%_ }); _%>
48
- } from './types.gen.js';
69
+ } from './types.gen<% if (esm) { %>.js<% } %>';
49
70
  <%_ } _%>
50
71
  <%_
51
72
  // Nested arrays of primitives (besides dates) don't need to have .map(...) called to convert them as the base case will be a noop
@@ -54,6 +75,9 @@ const canShortCircuitConversion = (property) => {
54
75
  if (["array", "dictionary"].includes(property.export)) {
55
76
  return !property.link || canShortCircuitConversion(property.link);
56
77
  }
78
+ if (property.export === "tuple") {
79
+ return property.properties.every(canShortCircuitConversion);
80
+ }
57
81
  return property.isPrimitive && !["date", "date-time"].includes(property.format);
58
82
  };
59
83
  // Render code to convert a date to its string representation
@@ -70,6 +94,8 @@ const renderNestedToJsonValue = (type, argumentType = undefined, depth = 0) => {
70
94
  return `(${itemIdentifier}${argType}) => ${["date", "date-time"].includes(type.format) ? renderToJsonDateValue(itemIdentifier, type.format) : itemIdentifier}`;
71
95
  } else if (type.export === "array") {
72
96
  return `(${itemIdentifier}${argType}) => ${itemIdentifier}.map(${renderNestedToJsonValue(type.link, argumentType, depth + 1)})`;
97
+ } else if (type.export === "tuple") {
98
+ return `(${itemIdentifier}${argType}) => ${renderTupleToJsonValue(type, itemIdentifier)}`;
73
99
  } else if (type.export === "dictionary") {
74
100
  return `(${itemIdentifier}${argType}) => $IO.$mapValues(${itemIdentifier}, ${renderNestedToJsonValue(type.link, argumentType, depth + 1)})`;
75
101
  } else if (type.type === 'unknown' && !["one-of", "any-of", "all-of"].includes(type.export)) {
@@ -79,6 +105,10 @@ const renderNestedToJsonValue = (type, argumentType = undefined, depth = 0) => {
79
105
  }
80
106
  return `$IO.${type.typescriptType || type.typescriptName}.toJson`;
81
107
  };
108
+ // Renders a tuple's positional element-wise conversion, e.g. `[f(v[0]), g(v[1])]`
109
+ const renderTupleToJsonValue = (property, value) => {
110
+ return `[${property.properties.map((member, i) => renderToJsonValue(member, `(${value} as any)[${i}]`)).join(', ')}]`;
111
+ };
82
112
  // Renders the code to transform a property of the model to its json representation from the model types
83
113
  const renderToJsonValue = (property, value, argumentType = undefined) => {
84
114
  let rendered = '';
@@ -90,6 +120,8 @@ const renderToJsonValue = (property, value, argumentType = undefined) => {
90
120
  } else if (property.export === "array") {
91
121
  const prefix = property.uniqueItems ? `Array.from(${value})` : `${value}`;
92
122
  rendered = `(${prefix}.map(${renderNestedToJsonValue(property.link, argumentType)}))`;
123
+ } else if (property.export === "tuple") {
124
+ rendered = `(${renderTupleToJsonValue(property, value)})`;
93
125
  } else if (property.export === "dictionary") {
94
126
  rendered = `($IO.$mapValues(${value}, ${renderNestedToJsonValue(property.link, argumentType)}))`;
95
127
  } else if (property.type !== "any") {
@@ -98,7 +130,7 @@ const renderToJsonValue = (property, value, argumentType = undefined) => {
98
130
  rendered = value;
99
131
  }
100
132
 
101
- if ((property.isPrimitive && ["date", "date-time"].includes(property.format)) || (!property.isPrimitive && ["array", "dictionary"].includes(property.export))) {
133
+ if ((property.isPrimitive && ["date", "date-time"].includes(property.format)) || (!property.isPrimitive && ["array", "tuple", "dictionary"].includes(property.export))) {
102
134
  rendered = property.isNullable ? `${value} === null ? null : ${rendered}` : rendered;
103
135
  }
104
136
  return rendered;
@@ -113,6 +145,8 @@ const renderNestedFromJsonValue = (type, argumentType = undefined, depth = 0) =>
113
145
  return `(${itemIdentifier}${argType}) => ${["date", "date-time"].includes(type.format) ? `new Date(${itemIdentifier})` : itemIdentifier}`;
114
146
  } else if (type.export === "array") {
115
147
  return `(${itemIdentifier}${argType}) => ${itemIdentifier}.map(${renderNestedFromJsonValue(type.link, argumentType, depth + 1)})`;
148
+ } else if (type.export === "tuple") {
149
+ return `(${itemIdentifier}${argType}) => ${renderTupleFromJsonValue(type, itemIdentifier)}`;
116
150
  } else if (type.export === "dictionary") {
117
151
  return `(${itemIdentifier}${argType}) => $IO.$mapValues(${itemIdentifier}, ${renderNestedFromJsonValue(type.link, argumentType, depth + 1)})`;
118
152
  } else if (type.type === 'unknown' && !["one-of", "any-of", "all-of"].includes(type.export)) {
@@ -122,6 +156,10 @@ const renderNestedFromJsonValue = (type, argumentType = undefined, depth = 0) =>
122
156
  }
123
157
  return `$IO.${type.typescriptType || type.typescriptName}.fromJson`;
124
158
  };
159
+ // Renders a tuple's positional element-wise revival, e.g. `[f(v[0]), g(v[1])]`
160
+ const renderTupleFromJsonValue = (property, value) => {
161
+ return `([${property.properties.map((member, i) => renderFromJsonValue(member, `(${value})[${i}]`)).join(', ')}] as ${property.typescriptType})`;
162
+ };
125
163
  // Renders the code to transform a property of the model from its json representation into the model types
126
164
  const renderFromJsonValue = (property, value, argumentType = undefined) => {
127
165
  let rendered = '';
@@ -132,6 +170,8 @@ const renderFromJsonValue = (property, value, argumentType = undefined) => {
132
170
  } else if (property.export === "array") {
133
171
  rendered = `((${value} as Array<any>).map(${renderNestedFromJsonValue(property.link, argumentType)}))`;
134
172
  rendered = property.uniqueItems ? `new Set(${rendered})` : rendered;
173
+ } else if (property.export === "tuple") {
174
+ rendered = renderTupleFromJsonValue(property, value);
135
175
  } else if (property.export === "dictionary") {
136
176
  rendered = `($IO.$mapValues(${value}, ${renderNestedFromJsonValue(property.link, argumentType)}))`;
137
177
  } else {
@@ -149,8 +189,13 @@ const renderResponseCondition = (code) => {
149
189
  }
150
190
  return `response.status === ${code}`;
151
191
  };
152
- // Renders the code which handles deserialising the response from a fetch call
192
+ // Renders the code which handles deserialising the response from a fetch call.
193
+ // A primitive on a JSON wire arrives JSON-encoded (a string body is `"hello"`,
194
+ // quotes included), so it must be JSON-parsed rather than read as raw text.
195
+ // Streaming chunks (options provided) keep raw-text semantics: an x-streaming
196
+ // chunk is an arbitrary fragment, not a complete JSON document.
153
197
  const renderResponse = (response, options) => {
198
+ const jsonWire = !options && isJsonResponse(response);
154
199
  let opts = options || {
155
200
  asText: 'await response.text()',
156
201
  asJson: 'await response.json()',
@@ -159,7 +204,13 @@ const renderResponse = (response, options) => {
159
204
  if (response.type === 'binary') {
160
205
  return opts.asBlob;
161
206
  }
162
- if ((response.isPrimitive || ['unknown', 'any'].includes(response.type)) && !['array', 'dictionary'].includes(response.export)) {
207
+ if ((response.isPrimitive || ['unknown', 'any'].includes(response.type)) && !['array', 'tuple', 'dictionary'].includes(response.export)) {
208
+ if (jsonWire) {
209
+ if (['date', 'date-time'].includes(response.format)) {
210
+ return `new Date(${opts.asJson})`;
211
+ }
212
+ return `${opts.asJson}${['unknown', 'any'].includes(response.type) ? ' as any' : ''}`;
213
+ }
163
214
  if (response.type === 'number') {
164
215
  return `Number(${opts.asText})`;
165
216
  } else if (response.type === 'boolean') {
@@ -170,7 +221,7 @@ const renderResponse = (response, options) => {
170
221
  return `${opts.asText}${['unknown', 'any'].includes(response.type) ? ' as any' : ''}`;
171
222
  }
172
223
  if (response.isEnum || response.export === 'enum') {
173
- return `(${opts.asText}) as ${response.typescriptType}`;
224
+ return `(${jsonWire ? opts.asJson : opts.asText}) as ${response.typescriptType}`;
174
225
  }
175
226
  return renderFromJsonValue(response, `(${opts.asJson})`);
176
227
  };
@@ -202,6 +253,22 @@ export class $IO {
202
253
  <%_ const toJsonName = isBase ? '$toJsonBase' : 'toJson'; _%>
203
254
  <%_ const fromJsonName = isBase ? '$fromJsonBase' : 'fromJson'; _%>
204
255
 
256
+ <%_ if (model.export === 'tuple') { _%>
257
+ public static <%- model.typescriptName %> = {
258
+ toJson: (model: <%- model.typescriptName %>): any => {
259
+ if (model === undefined || model === null) {
260
+ return model;
261
+ }
262
+ return <%- renderToJsonValue(model, 'model') %>;
263
+ },
264
+ fromJson: (json: any): <%- model.typescriptName %> => {
265
+ if (json === undefined || json === null) {
266
+ return json;
267
+ }
268
+ return <%- renderFromJsonValue(model, 'json') %>;
269
+ },
270
+ };
271
+ <%_ return; } _%>
205
272
  public static <%- model.typescriptName %> = {
206
273
  <%_ if (isBase) { _%>
207
274
  toJson: (model: <%- model.typescriptName %>): any => {
@@ -355,10 +422,15 @@ export class $IO {
355
422
  }
356
423
  <%_ } _%>
357
424
  <%_ if (model.composedModels.length > 0) { _%>
425
+ <%_ /* A non-discriminated union's members marshal via their partial form:
426
+ the value matches one member, so the others must convert only the
427
+ properties actually present rather than fabricate their own. */ _%>
358
428
  return {
359
429
  <%_ model.properties.filter(p => !p.isPrimitive && p.export !== 'array').forEach((composedType) => { _%>
360
430
  <%_ if (composedType.export === 'reference' && discriminatorBaseNames.has(composedType.type)) { _%>
361
431
  ...<%- composedMarshaller(composedType, 'fromJson') %>(json),
432
+ <%_ } else if (model.export !== 'all-of' && composedType.export === 'reference' && hasPartialMarshaller(composedType.type)) { _%>
433
+ ...$IO.<%- composedType.typescriptType %>.$fromJsonPartial(json),
362
434
  <%_ } else { _%>
363
435
  ...<%- renderFromJsonValue(composedType, 'json') %>,
364
436
  <%_ } _%>
@@ -398,6 +470,36 @@ export class $IO {
398
470
  };
399
471
  <%_ } _%>
400
472
  },
473
+ <%_ if (hasPartialMarshaller(model.name)) { _%>
474
+ <%_ /* Converts only the properties present on the wire value — a required
475
+ field that is absent is skipped, never fabricated (e.g. no
476
+ `new Date(undefined)`). Used solely when composing this model as a
477
+ member of a non-discriminated union, where the value may match a
478
+ different member; `fromJson` remains the fully-typed marshaller. */ _%>
479
+ $fromJsonPartial: (json: any): any => {
480
+ return {
481
+ <%_ if (model.hasPatternProperties && model.patternPropertiesModels.length > 0) { _%>
482
+ <%_ model.patternPropertiesModels.forEach(({ pattern, model: patternProperty }) => { _%>
483
+ ...$IO.$mapValues(Object.fromEntries(Object.entries(json).filter(([key]) => <% if (model.properties.length > 0) { %>![<%- model.properties.map(p => `'${p.name}'`).join(', ') %>].includes(key) && <% } %>
484
+ <%- matchPattern(pattern, 'key') %>
485
+ )), (patternProperty) => <%- renderFromJsonValue(patternProperty, 'patternProperty', 'any') %>),
486
+ <%_ }); _%>
487
+ <%_ } _%>
488
+ <%_ if (model.hasAdditionalProperties) { _%>
489
+ ...$IO.$mapValues(Object.fromEntries(Object.entries(json).filter(([key]) => <% if (model.properties.length > 0) { %>![<%- model.properties.map(p => `'${p.name}'`).join(', ') %>].includes(key)<% } %>
490
+ <%_ if (model.hasPatternProperties && model.patternPropertiesModels.length > 0) { _%>
491
+ <% if (model.properties.length > 0) { %>&& <% } %>!(<%- model.patternPropertiesModels.map(({ pattern }) => matchPattern(pattern, 'key')).join(' || ') %>)
492
+ <%_ } _%>
493
+ )), (additionalProperty) => <%- renderFromJsonValue(model.additionalPropertiesModel, 'additionalProperty', 'any') %>),
494
+ <%_ } _%>
495
+ <%_ model.properties.forEach((property) => { _%>
496
+ ...(json['<%- property.name %>'] === undefined ? {} : {
497
+ <%= property.typescriptName %>: <%- renderFromJsonValue(property, `json['${property.name}']`) %>,
498
+ }),
499
+ <%_ }); _%>
500
+ };
501
+ },
502
+ <%_ } _%>
401
503
  };
402
504
  <%_ }) _%>
403
505
  }
@@ -457,20 +559,44 @@ export class <%- className %> {
457
559
  );
458
560
  };
459
561
 
460
- private $url = (path: string, pathParameters: { [key: string]: any }, queryParameters: { [key: string]: any }, collectionFormats?: { [key: string]: 'multi' | 'csv' | 'ssv' | 'pipes' | 'deepObject' }): string => {
562
+ private $url = (path: string, pathParameters: { [key: string]: any }, queryParameters: { [key: string]: any }, collectionFormats?: { [key: string]: 'multi' | 'csv' | 'ssv' | 'pipes' | 'deepObject' }<% if (hasStyledPathParams) { %>, pathStyles?: { [key: string]: { style: 'matrix' | 'label'; explode: boolean } }<% } %><% if (hasAllowReservedParams) { %>, allowReserved?: string[]<% } %>): string => {
461
563
  const baseUrl = this.$config.url.endsWith('/') ? this.$config.url.slice(0, -1) : this.$config.url;
564
+ <%_ if (hasAllowReservedParams) { _%>
565
+ // Reserved characters stay literal when a query parameter declares allowReserved
566
+ const encodeQueryValue = (key: string, v: string): string =>
567
+ allowReserved?.includes(key) ? encodeURIComponent(v).replace(/%(2F|3A|3F|23|5B|5D|40|21|24|26|27|28|29|2A|2B|2C|3B|3D)/gi, (m) => decodeURIComponent(m)) : encodeURIComponent(v);
568
+ <%_ } _%>
569
+ <%_ if (hasStyledPathParams) { _%>
570
+ const pathWithParameters = Object.entries(pathParameters).reduce((withParams, [key, value]) => {
571
+ const pathStyle = pathStyles?.[key];
572
+ let rendered: string;
573
+ if (pathStyle?.style === 'matrix') {
574
+ // RFC 6570 path-style expansion: ;key=a,b (explode: ;key=a;key=b)
575
+ rendered = Array.isArray(value) && pathStyle.explode
576
+ ? value.map(v => `;${key}=${encodeURIComponent(`${v}`)}`).join('')
577
+ : `;${key}=${(Array.isArray(value) ? value : [value]).map(v => encodeURIComponent(`${v}`)).join(',')}`;
578
+ } else if (pathStyle?.style === 'label') {
579
+ // RFC 6570 label expansion: .a,b (explode: .a.b)
580
+ rendered = `.${(Array.isArray(value) ? value : [value]).map(v => encodeURIComponent(`${v}`)).join(pathStyle.explode ? '.' : ',')}`;
581
+ } else {
582
+ rendered = encodeURIComponent(`${value}`);
583
+ }
584
+ return withParams.replace(`{${key}}`, rendered);
585
+ }, path);
586
+ <%_ } else { _%>
462
587
  const pathWithParameters = Object.entries(pathParameters).reduce((withParams, [key, value]) =>
463
588
  withParams.replace(`{${key}}`, encodeURIComponent(`${value}`))
464
589
  , path);
590
+ <%_ } _%>
465
591
  const queryString = Object.entries(queryParameters).flatMap(([key, value]) => {
466
592
  if (Array.isArray(value) && collectionFormats?.[key] === 'multi') {
467
- return value.map(v => `${encodeURIComponent(key)}=${encodeURIComponent(`${v}`)}`);
593
+ return value.map(v => `${encodeURIComponent(key)}=<% if (hasAllowReservedParams) { %>${encodeQueryValue(key, `${v}`)}<% } else { %>${encodeURIComponent(`${v}`)}<% } %>`);
468
594
  }
469
595
  if (collectionFormats?.[key] === 'deepObject' && value !== null && typeof value === 'object') {
470
596
  return this.$deepObject(encodeURIComponent(key), value);
471
597
  }
472
598
  const delimiter = this.$collectionDelimiters[collectionFormats?.[key] ?? 'csv'] ?? ',';
473
- return [`${encodeURIComponent(key)}=${encodeURIComponent(Array.isArray(value) ? value.map(String).join(delimiter) : String(value))}`];
599
+ return [`${encodeURIComponent(key)}=<% if (hasAllowReservedParams) { %>${encodeQueryValue(key, Array.isArray(value) ? value.map(String).join(delimiter) : String(value))}<% } else { %>${encodeURIComponent(Array.isArray(value) ? value.map(String).join(delimiter) : String(value))}<% } %>`];
474
600
  }).join('&');
475
601
  return baseUrl + pathWithParameters + (queryString ? `?${queryString}` : '');
476
602
  };
@@ -486,18 +612,33 @@ export class <%- className %> {
486
612
  };
487
613
 
488
614
  <%_ if (hasMultipartBody) { _%>
489
- private $formData = (model: { [key: string]: any }): FormData => {
615
+ private $formData = (
616
+ model: { [key: string]: any },
617
+ partContentTypes?: { [key: string]: string },
618
+ ): FormData => {
490
619
  const formData = new FormData();
491
620
  const append = (key: string, value: any): void => {
492
621
  if (value === undefined || value === null) {
493
622
  return;
494
623
  }
624
+ const partContentType = partContentTypes?.[key];
495
625
  if (value instanceof Blob || typeof value === 'string') {
496
- formData.append(key, value);
626
+ // A declared part content type overrides the default (text/plain for
627
+ // strings, the Blob's own type otherwise)
628
+ if (partContentType) {
629
+ formData.append(key, new Blob([value], { type: partContentType }));
630
+ } else {
631
+ formData.append(key, value);
632
+ }
497
633
  } else if (Array.isArray(value)) {
498
634
  value.forEach((v) => append(key, v));
499
635
  } else if (typeof value === 'object') {
500
- formData.append(key, JSON.stringify(value));
636
+ const serialized = JSON.stringify(value);
637
+ if (partContentType) {
638
+ formData.append(key, new Blob([serialized], { type: partContentType }));
639
+ } else {
640
+ formData.append(key, serialized);
641
+ }
501
642
  } else {
502
643
  formData.append(key, String(value));
503
644
  }
@@ -506,6 +647,26 @@ export class <%- className %> {
506
647
  return formData;
507
648
  };
508
649
 
650
+ <%_ } _%>
651
+ <%_ if (hasUrlEncodedBody) { _%>
652
+ private $urlEncodedForm = (model: { [key: string]: any }): URLSearchParams => {
653
+ const params = new URLSearchParams();
654
+ const append = (key: string, value: any): void => {
655
+ if (value === undefined || value === null) {
656
+ return;
657
+ }
658
+ if (Array.isArray(value)) {
659
+ value.forEach((v) => append(key, v));
660
+ } else if (typeof value === 'object') {
661
+ params.append(key, JSON.stringify(value));
662
+ } else {
663
+ params.append(key, String(value));
664
+ }
665
+ };
666
+ Object.entries(model).forEach(([key, value]) => append(key, value));
667
+ return params;
668
+ };
669
+
509
670
  <%_ } _%>
510
671
  private $fetch: typeof fetch = (...args) => (this.$config.fetch ?? fetch)(...args);
511
672
  <%_ allOperations.forEach((op) => { _%>
@@ -517,6 +678,14 @@ export class <%- className %> {
517
678
  <%_ ['path', 'query', 'header'].forEach((position) => { _%>
518
679
  <%_ if (op.parameters.map(p => p.in).includes(position)) { _%>
519
680
  const <%- position %>Parameters: {[key: string]: any} = $IO.<%- op.operationIdPascalCase %>Request<%- upperFirst(position) %>Parameters.toJson(input);
681
+ <%_ /* A content-based parameter (declared with `content` rather than
682
+ `schema`) is serialised to its media type — JSON — as a single
683
+ value. */ _%>
684
+ <%_ op.parameters.filter(p => p.in === position && p.mediaType === 'application/json').forEach((parameter) => { _%>
685
+ if (<%- position %>Parameters['<%- parameter.prop %>'] !== undefined) {
686
+ <%- position %>Parameters['<%- parameter.prop %>'] = JSON.stringify(<%- position %>Parameters['<%- parameter.prop %>']);
687
+ }
688
+ <%_ }); _%>
520
689
  <%_ } else { _%>
521
690
  const <%- position %>Parameters: {[key: string]: any} = {};
522
691
  <%_ } _%>
@@ -552,6 +721,8 @@ export class <%- className %> {
552
721
  in a single object literal. */ _%>
553
722
  <%_ const queryCollectionParams = op.parameters.filter(p => p.collectionFormat && p.in === 'query'); _%>
554
723
  <%_ const headerCollectionParams = op.parameters.filter(p => p.collectionFormat && p.in === 'header'); _%>
724
+ <%_ const styledPathParams = op.parameters.filter(p => p.pathStyle && p.in === 'path'); _%>
725
+ <%_ const allowReservedParams = op.parameters.filter(p => p.allowReserved && p.in === 'query'); _%>
555
726
  <%_ if (queryCollectionParams.length > 0) { _%>
556
727
  const queryCollectionFormats = {
557
728
  <%_ queryCollectionParams.forEach((parameter) => { _%>
@@ -559,6 +730,13 @@ export class <%- className %> {
559
730
  <%_ }); _%>
560
731
  } as const;
561
732
  <%_ } _%>
733
+ <%_ if (styledPathParams.length > 0) { _%>
734
+ const pathParameterStyles = {
735
+ <%_ styledPathParams.forEach((parameter) => { _%>
736
+ '<%- parameter.prop %>': { style: '<%- parameter.pathStyle %>', explode: <%- !!parameter.pathExplode %> },
737
+ <%_ }); _%>
738
+ } as const;
739
+ <%_ } _%>
562
740
  <%_ if (headerCollectionParams.length > 0) { _%>
563
741
  const headerCollectionFormats = {
564
742
  <%_ headerCollectionParams.forEach((parameter) => { _%>
@@ -572,7 +750,12 @@ export class <%- className %> {
572
750
  parts, primitives serialise to strings, and fetch computes the
573
751
  boundary itself (so the Content-Type header is intentionally unset
574
752
  above). */ _%>
575
- const body = <% if (!op.parametersBody.isRequired) { %>input === undefined ? undefined : <% } %>this.$formData(<%- op.explicitRequestBodyParameter ? `$IO.${op.operationIdPascalCase}RequestBodyParameters.toJson(input).${op.explicitRequestBodyParameter.prop}` : renderToJsonValue(op.parametersBody, 'input') %>);
753
+ const body = <% if (!op.parametersBody.isRequired) { %>input === undefined ? undefined : <% } %>this.$formData(<%- op.explicitRequestBodyParameter ? `$IO.${op.operationIdPascalCase}RequestBodyParameters.toJson(input).${op.explicitRequestBodyParameter.prop}` : renderToJsonValue(op.parametersBody, 'input') %><% if (op.parametersBody.partContentTypes) { %>, <%- JSON.stringify(op.parametersBody.partContentTypes) %><% } %>);
754
+ <%_ } else if (bodyMediaTypeOf(op) === 'application/x-www-form-urlencoded') { _%>
755
+ <%_ /* A urlencoded body is sent as `key=value&...` pairs — the JSON
756
+ serialisation the wire type declares would be rejected by the
757
+ server's form parser. */ _%>
758
+ const body = <% if (!op.parametersBody.isRequired) { %>input === undefined ? undefined : <% } %>this.$urlEncodedForm(<%- op.explicitRequestBodyParameter ? `$IO.${op.operationIdPascalCase}RequestBodyParameters.toJson(input).${op.explicitRequestBodyParameter.prop}` : renderToJsonValue(op.parametersBody, 'input') %>).toString();
576
759
  <%_ } else if (op.parametersBody.isPrimitive && ['number', 'boolean', 'string'].includes(op.parametersBody.type) && !['array', 'dictionary'].includes(op.parametersBody.export) && !["date", "date-time"].includes(op.parametersBody.format)) { _%>
577
760
  const body = <% if (!op.parametersBody.isRequired) { %>input === undefined ? undefined : <% } %>String(input<%- op.explicitRequestBodyParameter ? `.${op.explicitRequestBodyParameter.typescriptName}` : '' %>);
578
761
  <%_ } else if (op.parametersBody.isPrimitive && ["date", "date-time"].includes(op.parametersBody.format)) { _%>
@@ -604,7 +787,7 @@ export class <%- className %> {
604
787
  const body = undefined;
605
788
  <%_ } _%>
606
789
 
607
- const response = await this.$fetch(this.$url('<%- op.path %>', pathParameters, queryParameters<% if (queryCollectionParams.length > 0) { %>, queryCollectionFormats<% } %>), {
790
+ const response = await this.$fetch(this.$url('<%- op.path %>', pathParameters, queryParameters<% if (queryCollectionParams.length > 0 || styledPathParams.length > 0 || allowReservedParams.length > 0) { %>, <%- queryCollectionParams.length > 0 ? 'queryCollectionFormats' : 'undefined' %><% } %><% if (styledPathParams.length > 0 || allowReservedParams.length > 0) { %>, <%- styledPathParams.length > 0 ? 'pathParameterStyles' : 'undefined' %><% } %><% if (allowReservedParams.length > 0) { %>, [<%- allowReservedParams.map(p => `'${p.prop}'`).join(', ') %>]<% } %>), {
608
791
  headers: this.$headers(headerParameters<% if (headerCollectionParams.length > 0) { %>, headerCollectionFormats<% } %>),
609
792
  method: '<%- op.method %>',
610
793
  body,
@@ -27,6 +27,8 @@ _%>
27
27
  <%_ }); _%>
28
28
  <%_ } else if (isComposite) { _%>
29
29
  <%- docString(model, '') %>export type <%- model.typescriptName %> =<% model.properties.forEach((composedType, i) => { %><% if (i > 0) { %><% if (model.export === "all-of") { %> &<% } else { %> |<% } %><% } %> <%- composedType.typescriptType %><% }); %>;
30
+ <%_ } else if (model.export === "tuple") { _%>
31
+ <%- docString(model, '') %>export type <%= model.typescriptName %> = <% if (model.isNullable) { %>null | <% } %>[<% model.properties.forEach((member, i) => { %><% if (i > 0) { %>, <% } %><%- member.typescriptType %><%= (member.isNullable && member.type !== 'null') ? ' | null' : '' %><% }); %>];
30
32
  <%_ } else { _%>
31
33
  <%- docString(model, '') %>export type <%= model.typescriptName %> = <% if (model.isNullable && model.type !== 'null') { %>null | <% } %>{
32
34
  <%_ if (model.export === "dictionary" && model.link) { _%>
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { generateFiles } from "@nx/devkit";
4
+ */ import { generateFiles, logger } from "@nx/devkit";
5
5
  import * as path from "path";
6
6
  import { formatFilesInSubtree } from "../../utils/format.js";
7
+ import { esmVars } from "../../utils/module-format.js";
7
8
  import { buildOpenApiCodeGenData } from "../utils/codegen-data.js";
8
9
  import { parseOpenApiSpec } from "../utils/parse.js";
9
10
  /**
@@ -17,12 +18,36 @@ import { parseOpenApiSpec } from "../utils/parse.js";
17
18
  * Build a data structure which can be used to generate code from OpenAPI
18
19
  */ export const buildOpenApiCodeGenerationData = async (tree, specPath)=>{
19
20
  const spec = await parseOpenApiSpec(tree, specPath);
21
+ warnForUnsupportedFeatures(spec);
20
22
  return buildOpenApiCodeGenData(spec);
21
23
  };
24
+ /**
25
+ * Warn for spec features the generated client does not implement, so their
26
+ * omission is never silent.
27
+ */ const warnForUnsupportedFeatures = (spec)=>{
28
+ if (Object.keys(spec.webhooks ?? {}).length > 0) {
29
+ logger.warn('OpenAPI webhooks are not supported and no client code is generated for them');
30
+ }
31
+ for (const [p, pathItem] of Object.entries(spec.paths ?? {})){
32
+ for (const [method, op] of Object.entries(pathItem ?? {})){
33
+ if (typeof op !== 'object' || op === null) continue;
34
+ const operation = op;
35
+ if (Object.keys(operation.callbacks ?? {}).length > 0) {
36
+ logger.warn(`Operation ${method.toUpperCase()} ${p} declares callbacks, which are not supported and are ignored`);
37
+ }
38
+ if ((operation.servers ?? []).length > 0) {
39
+ logger.warn(`Operation ${method.toUpperCase()} ${p} declares operation-level servers, which are ignored — the client always uses its configured url`);
40
+ }
41
+ }
42
+ }
43
+ };
22
44
  /**
23
45
  * Generate an OpenAPI typescript client in the target directory
24
46
  */ export const generateOpenApiTsClient = (tree, data, outputPath)=>{
25
- generateFiles(tree, path.join(import.meta.dirname, 'files'), outputPath, data);
47
+ generateFiles(tree, path.join(import.meta.dirname, 'files'), outputPath, {
48
+ ...data,
49
+ ...esmVars(tree)
50
+ });
26
51
  };
27
52
  export default openApiTsClientGenerator;
28
53
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/ts-client/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, type Tree } from '@nx/devkit';\nimport * as path from 'path';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { buildOpenApiCodeGenData } from '../utils/codegen-data';\nimport type { CodeGenData } from '../utils/codegen-data/types';\nimport { parseOpenApiSpec } from '../utils/parse';\nimport type { OpenApiTsClientGeneratorSchema } from './schema';\n\n/**\n * Generates typescript client from an openapi spec\n */\nexport const openApiTsClientGenerator = async (\n tree: Tree,\n options: OpenApiTsClientGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n\n generateOpenApiTsClient(tree, data, options.outputPath);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Build a data structure which can be used to generate code from OpenAPI\n */\nexport const buildOpenApiCodeGenerationData = async (\n tree: Tree,\n specPath: string,\n) => {\n const spec = await parseOpenApiSpec(tree, specPath);\n return buildOpenApiCodeGenData(spec);\n};\n\n/**\n * Generate an OpenAPI typescript client in the target directory\n */\nexport const generateOpenApiTsClient = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n) => {\n generateFiles(\n tree,\n path.join(import.meta.dirname, 'files'),\n outputPath,\n data,\n );\n};\n\nexport default openApiTsClientGenerator;\n"],"names":["generateFiles","path","formatFilesInSubtree","buildOpenApiCodeGenData","parseOpenApiSpec","openApiTsClientGenerator","tree","options","data","buildOpenApiCodeGenerationData","openApiSpecPath","generateOpenApiTsClient","outputPath","specPath","spec","join","dirname"],"mappings":"AAAA;;;CAGC,GACD,SAASA,aAAa,QAAmB,aAAa;AACtD,YAAYC,UAAU,OAAO;AAC7B,SAASC,oBAAoB,QAAQ,wBAAqB;AAC1D,SAASC,uBAAuB,QAAQ,2BAAwB;AAEhE,SAASC,gBAAgB,QAAQ,oBAAiB;AAGlD;;CAEC,GACD,OAAO,MAAMC,2BAA2B,OACtCC,MACAC;IAEA,MAAMC,OAAO,MAAMC,+BACjBH,MACAC,QAAQG,eAAe;IAGzBC,wBAAwBL,MAAME,MAAMD,QAAQK,UAAU;IAEtD,MAAMV,qBAAqBI;AAC7B,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMG,iCAAiC,OAC5CH,MACAO;IAEA,MAAMC,OAAO,MAAMV,iBAAiBE,MAAMO;IAC1C,OAAOV,wBAAwBW;AACjC,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMH,0BAA0B,CACrCL,MACAE,MACAI;IAEAZ,cACEM,MACAL,KAAKc,IAAI,CAAC,YAAYC,OAAO,EAAE,UAC/BJ,YACAJ;AAEJ,EAAE;AAEF,eAAeH,yBAAyB"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/ts-client/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, logger, type Tree } from '@nx/devkit';\nimport * as path from 'path';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { esmVars } from '../../utils/module-format';\nimport { buildOpenApiCodeGenData } from '../utils/codegen-data';\nimport type { CodeGenData } from '../utils/codegen-data/types';\nimport { parseOpenApiSpec } from '../utils/parse';\nimport type { Spec } from '../utils/types';\nimport type { OpenApiTsClientGeneratorSchema } from './schema';\n\n/**\n * Generates typescript client from an openapi spec\n */\nexport const openApiTsClientGenerator = async (\n tree: Tree,\n options: OpenApiTsClientGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n\n generateOpenApiTsClient(tree, data, options.outputPath);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Build a data structure which can be used to generate code from OpenAPI\n */\nexport const buildOpenApiCodeGenerationData = async (\n tree: Tree,\n specPath: string,\n) => {\n const spec = await parseOpenApiSpec(tree, specPath);\n warnForUnsupportedFeatures(spec);\n return buildOpenApiCodeGenData(spec);\n};\n\n/**\n * Warn for spec features the generated client does not implement, so their\n * omission is never silent.\n */\nconst warnForUnsupportedFeatures = (spec: Spec) => {\n if (Object.keys((spec as { webhooks?: object }).webhooks ?? {}).length > 0) {\n logger.warn(\n 'OpenAPI webhooks are not supported and no client code is generated for them',\n );\n }\n for (const [p, pathItem] of Object.entries(spec.paths ?? {})) {\n for (const [method, op] of Object.entries(pathItem ?? {})) {\n if (typeof op !== 'object' || op === null) continue;\n const operation = op as {\n callbacks?: object;\n servers?: unknown[];\n };\n if (Object.keys(operation.callbacks ?? {}).length > 0) {\n logger.warn(\n `Operation ${method.toUpperCase()} ${p} declares callbacks, which are not supported and are ignored`,\n );\n }\n if ((operation.servers ?? []).length > 0) {\n logger.warn(\n `Operation ${method.toUpperCase()} ${p} declares operation-level servers, which are ignored — the client always uses its configured url`,\n );\n }\n }\n }\n};\n\n/**\n * Generate an OpenAPI typescript client in the target directory\n */\nexport const generateOpenApiTsClient = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n) => {\n generateFiles(\n tree,\n path.join(import.meta.dirname, 'files'),\n outputPath,\n { ...data, ...esmVars(tree) },\n );\n};\n\nexport default openApiTsClientGenerator;\n"],"names":["generateFiles","logger","path","formatFilesInSubtree","esmVars","buildOpenApiCodeGenData","parseOpenApiSpec","openApiTsClientGenerator","tree","options","data","buildOpenApiCodeGenerationData","openApiSpecPath","generateOpenApiTsClient","outputPath","specPath","spec","warnForUnsupportedFeatures","Object","keys","webhooks","length","warn","p","pathItem","entries","paths","method","op","operation","callbacks","toUpperCase","servers","join","dirname"],"mappings":"AAAA;;;CAGC,GACD,SAASA,aAAa,EAAEC,MAAM,QAAmB,aAAa;AAC9D,YAAYC,UAAU,OAAO;AAC7B,SAASC,oBAAoB,QAAQ,wBAAqB;AAC1D,SAASC,OAAO,QAAQ,+BAA4B;AACpD,SAASC,uBAAuB,QAAQ,2BAAwB;AAEhE,SAASC,gBAAgB,QAAQ,oBAAiB;AAIlD;;CAEC,GACD,OAAO,MAAMC,2BAA2B,OACtCC,MACAC;IAEA,MAAMC,OAAO,MAAMC,+BACjBH,MACAC,QAAQG,eAAe;IAGzBC,wBAAwBL,MAAME,MAAMD,QAAQK,UAAU;IAEtD,MAAMX,qBAAqBK;AAC7B,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMG,iCAAiC,OAC5CH,MACAO;IAEA,MAAMC,OAAO,MAAMV,iBAAiBE,MAAMO;IAC1CE,2BAA2BD;IAC3B,OAAOX,wBAAwBW;AACjC,EAAE;AAEF;;;CAGC,GACD,MAAMC,6BAA6B,CAACD;IAClC,IAAIE,OAAOC,IAAI,CAAC,AAACH,KAA+BI,QAAQ,IAAI,CAAC,GAAGC,MAAM,GAAG,GAAG;QAC1EpB,OAAOqB,IAAI,CACT;IAEJ;IACA,KAAK,MAAM,CAACC,GAAGC,SAAS,IAAIN,OAAOO,OAAO,CAACT,KAAKU,KAAK,IAAI,CAAC,GAAI;QAC5D,KAAK,MAAM,CAACC,QAAQC,GAAG,IAAIV,OAAOO,OAAO,CAACD,YAAY,CAAC,GAAI;YACzD,IAAI,OAAOI,OAAO,YAAYA,OAAO,MAAM;YAC3C,MAAMC,YAAYD;YAIlB,IAAIV,OAAOC,IAAI,CAACU,UAAUC,SAAS,IAAI,CAAC,GAAGT,MAAM,GAAG,GAAG;gBACrDpB,OAAOqB,IAAI,CACT,CAAC,UAAU,EAAEK,OAAOI,WAAW,GAAG,CAAC,EAAER,EAAE,4DAA4D,CAAC;YAExG;YACA,IAAI,AAACM,CAAAA,UAAUG,OAAO,IAAI,EAAE,AAAD,EAAGX,MAAM,GAAG,GAAG;gBACxCpB,OAAOqB,IAAI,CACT,CAAC,UAAU,EAAEK,OAAOI,WAAW,GAAG,CAAC,EAAER,EAAE,gGAAgG,CAAC;YAE5I;QACF;IACF;AACF;AAEA;;CAEC,GACD,OAAO,MAAMV,0BAA0B,CACrCL,MACAE,MACAI;IAEAd,cACEQ,MACAN,KAAK+B,IAAI,CAAC,YAAYC,OAAO,EAAE,UAC/BpB,YACA;QAAE,GAAGJ,IAAI;QAAE,GAAGN,QAAQI,KAAK;IAAC;AAEhC,EAAE;AAEF,eAAeD,yBAAyB"}
@@ -41,9 +41,9 @@ import type {
41
41
  <%_ uniq(allOperations.flatMap((op) => op.isInfiniteQuery && op.infiniteQueryCursorProperty && modelsByName[op.infiniteQueryCursorProperty.type] ? [modelsByName[op.infiniteQueryCursorProperty.type].typescriptType] : [])).forEach((cursorTypeModel) => { _%>
42
42
  <%- cursorTypeModel %>,
43
43
  <%_ }); _%>
44
- } from './types.gen.js';
44
+ } from './types.gen<% if (esm) { %>.js<% } %>';
45
45
  <%_ } _%>
46
- import { <%- className %> } from './client.gen.js';
46
+ import { <%- className %> } from './client.gen<% if (esm) { %>.js<% } %>';
47
47
 
48
48
  export interface <%- className %>OptionsProxyConfig {
49
49
  client: <%- className %>;
@@ -4,6 +4,7 @@
4
4
  */ import { generateFiles } from "@nx/devkit";
5
5
  import path from "path";
6
6
  import { formatFilesInSubtree } from "../../utils/format.js";
7
+ import { esmVars } from "../../utils/module-format.js";
7
8
  import { buildOpenApiCodeGenerationData, generateOpenApiTsClient } from "../ts-client/generator.js";
8
9
  /**
9
10
  * Generates typescript hooks from an openapi spec
@@ -16,7 +17,10 @@ import { buildOpenApiCodeGenerationData, generateOpenApiTsClient } from "../ts-c
16
17
  /**
17
18
  * Generate OpenAPI typescript hooks in the target directory
18
19
  */ export const generateOpenApiTsHooks = (tree, data, outputPath)=>{
19
- generateFiles(tree, path.join(import.meta.dirname, 'files'), outputPath, data);
20
+ generateFiles(tree, path.join(import.meta.dirname, 'files'), outputPath, {
21
+ ...data,
22
+ ...esmVars(tree)
23
+ });
20
24
  };
21
25
  export default openApiTsHooksGenerator;
22
26
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/ts-hooks/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, type Tree } from '@nx/devkit';\nimport path from 'path';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport {\n buildOpenApiCodeGenerationData,\n generateOpenApiTsClient,\n} from '../ts-client/generator';\nimport type { CodeGenData } from '../utils/codegen-data/types';\nimport type { OpenApiTsHooksGeneratorSchema } from './schema';\n\n/**\n * Generates typescript hooks from an openapi spec\n */\nexport const openApiTsHooksGenerator = async (\n tree: Tree,\n options: OpenApiTsHooksGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n\n generateOpenApiTsClient(tree, data, options.outputPath);\n generateOpenApiTsHooks(tree, data, options.outputPath);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Generate OpenAPI typescript hooks in the target directory\n */\nexport const generateOpenApiTsHooks = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n) => {\n generateFiles(\n tree,\n path.join(import.meta.dirname, 'files'),\n outputPath,\n data,\n );\n};\n\nexport default openApiTsHooksGenerator;\n"],"names":["generateFiles","path","formatFilesInSubtree","buildOpenApiCodeGenerationData","generateOpenApiTsClient","openApiTsHooksGenerator","tree","options","data","openApiSpecPath","outputPath","generateOpenApiTsHooks","join","dirname"],"mappings":"AAAA;;;CAGC,GACD,SAASA,aAAa,QAAmB,aAAa;AACtD,OAAOC,UAAU,OAAO;AACxB,SAASC,oBAAoB,QAAQ,wBAAqB;AAC1D,SACEC,8BAA8B,EAC9BC,uBAAuB,QAClB,4BAAyB;AAIhC;;CAEC,GACD,OAAO,MAAMC,0BAA0B,OACrCC,MACAC;IAEA,MAAMC,OAAO,MAAML,+BACjBG,MACAC,QAAQE,eAAe;IAGzBL,wBAAwBE,MAAME,MAAMD,QAAQG,UAAU;IACtDC,uBAAuBL,MAAME,MAAMD,QAAQG,UAAU;IAErD,MAAMR,qBAAqBI;AAC7B,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMK,yBAAyB,CACpCL,MACAE,MACAE;IAEAV,cACEM,MACAL,KAAKW,IAAI,CAAC,YAAYC,OAAO,EAAE,UAC/BH,YACAF;AAEJ,EAAE;AAEF,eAAeH,wBAAwB"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/ts-hooks/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, type Tree } from '@nx/devkit';\nimport path from 'path';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { esmVars } from '../../utils/module-format';\nimport {\n buildOpenApiCodeGenerationData,\n generateOpenApiTsClient,\n} from '../ts-client/generator';\nimport type { CodeGenData } from '../utils/codegen-data/types';\nimport type { OpenApiTsHooksGeneratorSchema } from './schema';\n\n/**\n * Generates typescript hooks from an openapi spec\n */\nexport const openApiTsHooksGenerator = async (\n tree: Tree,\n options: OpenApiTsHooksGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n\n generateOpenApiTsClient(tree, data, options.outputPath);\n generateOpenApiTsHooks(tree, data, options.outputPath);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Generate OpenAPI typescript hooks in the target directory\n */\nexport const generateOpenApiTsHooks = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n) => {\n generateFiles(\n tree,\n path.join(import.meta.dirname, 'files'),\n outputPath,\n { ...data, ...esmVars(tree) },\n );\n};\n\nexport default openApiTsHooksGenerator;\n"],"names":["generateFiles","path","formatFilesInSubtree","esmVars","buildOpenApiCodeGenerationData","generateOpenApiTsClient","openApiTsHooksGenerator","tree","options","data","openApiSpecPath","outputPath","generateOpenApiTsHooks","join","dirname"],"mappings":"AAAA;;;CAGC,GACD,SAASA,aAAa,QAAmB,aAAa;AACtD,OAAOC,UAAU,OAAO;AACxB,SAASC,oBAAoB,QAAQ,wBAAqB;AAC1D,SAASC,OAAO,QAAQ,+BAA4B;AACpD,SACEC,8BAA8B,EAC9BC,uBAAuB,QAClB,4BAAyB;AAIhC;;CAEC,GACD,OAAO,MAAMC,0BAA0B,OACrCC,MACAC;IAEA,MAAMC,OAAO,MAAML,+BACjBG,MACAC,QAAQE,eAAe;IAGzBL,wBAAwBE,MAAME,MAAMD,QAAQG,UAAU;IACtDC,uBAAuBL,MAAME,MAAMD,QAAQG,UAAU;IAErD,MAAMT,qBAAqBK;AAC7B,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMK,yBAAyB,CACpCL,MACAE,MACAE;IAEAX,cACEO,MACAN,KAAKY,IAAI,CAAC,YAAYC,OAAO,EAAE,UAC/BH,YACA;QAAE,GAAGF,IAAI;QAAE,GAAGN,QAAQI,KAAK;IAAC;AAEhC,EAAE;AAEF,eAAeD,wBAAwB"}
@@ -14,6 +14,8 @@ const toTypescriptPrimitive = (property)=>{
14
14
  }
15
15
  return property.type;
16
16
  };
17
+ // A nullable tuple member renders as a union with null.
18
+ const memberType = (rendered, member)=>member.isNullable && member.type !== 'null' ? `${rendered} | null` : rendered;
17
19
  export const toTypeScriptType = (property)=>{
18
20
  // A discriminated subtype's discriminator property renders as its literal
19
21
  // tag, making the union a true (narrowable) tagged union.
@@ -29,6 +31,8 @@ export const toTypeScriptType = (property)=>{
29
31
  return toTypescriptPrimitive(property);
30
32
  case 'array':
31
33
  return `Array<${valueType()}>`;
34
+ case 'tuple':
35
+ return `[${property.properties.map((member)=>memberType(toTypeScriptType(member), member)).join(', ')}]`;
32
36
  case 'dictionary':
33
37
  return `{ [key: string]: ${valueType()}; }`;
34
38
  case 'one-of':
@@ -117,6 +121,8 @@ export const toPythonType = (property)=>{
117
121
  return toPythonPrimitive(property);
118
122
  case 'array':
119
123
  return `List[${valueType()}]`;
124
+ case 'tuple':
125
+ return `Tuple[${property.properties.map((member)=>toPythonType(member)).join(', ')}]`;
120
126
  case 'dictionary':
121
127
  return `Dict[str, ${valueType()}]`;
122
128
  case 'one-of':