@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.
- package/LICENSE-THIRD-PARTY +75 -86
- package/generators.json +27 -0
- package/package.json +10 -10
- package/src/connection/generator.js +12 -1
- package/src/connection/generator.js.map +1 -1
- package/src/connection/supported-connections.d.ts +10 -1
- package/src/connection/supported-connections.js +13 -0
- package/src/connection/supported-connections.js.map +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +21 -21
- package/src/infra/app/files/app/src/main.ts.template +1 -1
- package/src/infra/app/files/app/src/stages/application-stage.ts.template +1 -1
- package/src/infra/app/generator.js +3 -1
- package/src/infra/app/generator.js.map +1 -1
- package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +12 -12
- package/src/open-api/ts-client/__snapshots__/generator.composite-types.spec.ts.snap +74 -10
- package/src/open-api/ts-client/__snapshots__/generator.content-type.spec.ts.snap +22 -4
- package/src/open-api/ts-client/__snapshots__/generator.duplicate-types.spec.ts.snap +53 -8
- package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +32 -4
- package/src/open-api/ts-client/__snapshots__/generator.fast-api-gaps.spec.ts.snap +736 -0
- package/src/open-api/ts-client/__snapshots__/generator.fast-api.spec.ts.snap +86 -11
- package/src/open-api/ts-client/__snapshots__/generator.multipart.spec.ts.snap +21 -3
- package/src/open-api/ts-client/__snapshots__/generator.primitive-types.spec.ts.snap +2 -2
- package/src/open-api/ts-client/__snapshots__/generator.request.spec.ts.snap +6 -6
- package/src/open-api/ts-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +2 -2
- package/src/open-api/ts-client/__snapshots__/generator.spec-compliance.spec.ts.snap +1883 -0
- package/src/open-api/ts-client/__snapshots__/generator.tags.spec.ts.snap +4 -4
- package/src/open-api/ts-client/files/client.gen.ts.template +196 -13
- package/src/open-api/ts-client/files/types.gen.ts.template +2 -0
- package/src/open-api/ts-client/generator.js +27 -2
- package/src/open-api/ts-client/generator.js.map +1 -1
- package/src/open-api/ts-hooks/files/options-proxy.gen.ts.template +2 -2
- package/src/open-api/ts-hooks/generator.js +5 -1
- package/src/open-api/ts-hooks/generator.js.map +1 -1
- package/src/open-api/utils/codegen-data/languages.js +6 -0
- package/src/open-api/utils/codegen-data/languages.js.map +1 -1
- package/src/open-api/utils/codegen-data/types.d.ts +16 -1
- package/src/open-api/utils/codegen-data/types.js.map +1 -1
- package/src/open-api/utils/codegen-data.js +71 -0
- package/src/open-api/utils/codegen-data.js.map +1 -1
- package/src/open-api/utils/normalise.js +53 -8
- package/src/open-api/utils/normalise.js.map +1 -1
- package/src/open-api/utils/parser.js +48 -15
- package/src/open-api/utils/parser.js.map +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +5 -3
- package/src/preset/generator.d.ts +1 -1
- package/src/preset/generator.js +5 -2
- package/src/preset/generator.js.map +1 -1
- package/src/preset/schema.d.js.map +1 -1
- package/src/preset/schema.d.ts +2 -0
- package/src/preset/schema.json +6 -0
- package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +7 -7
- package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +8 -8
- package/src/py/agent/__snapshots__/generator.protocols.spec.ts.snap +89 -3
- package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +12 -12
- package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +91 -5
- package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2038 -0
- package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +104 -0
- package/src/py/rdb/agent-connection/generator.d.ts +10 -0
- package/src/py/rdb/agent-connection/generator.js +46 -0
- package/src/py/rdb/agent-connection/generator.js.map +1 -0
- package/src/py/rdb/agent-connection/schema.d.js +8 -0
- package/src/py/rdb/agent-connection/schema.d.js.map +1 -0
- package/src/py/rdb/agent-connection/schema.d.ts +15 -0
- package/src/py/rdb/agent-connection/schema.json +27 -0
- package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +44 -0
- package/src/py/rdb/fast-api-connection/files/__apiModuleName__/dependencies/__rdbNameSnake__.py.template +14 -0
- package/src/py/rdb/fast-api-connection/generator.d.ts +10 -0
- package/src/py/rdb/fast-api-connection/generator.js +54 -0
- package/src/py/rdb/fast-api-connection/generator.js.map +1 -0
- package/src/py/rdb/fast-api-connection/schema.d.js +8 -0
- package/src/py/rdb/fast-api-connection/schema.d.js.map +1 -0
- package/src/py/rdb/fast-api-connection/schema.d.ts +13 -0
- package/src/py/rdb/fast-api-connection/schema.json +23 -0
- package/src/py/rdb/files/Dockerfile.create-db-user.template +10 -0
- package/src/py/rdb/files/Dockerfile.migration.template +10 -0
- package/src/py/rdb/files/__name__/__init__.py.template +3 -0
- package/src/py/rdb/files/__name__/connection.py.template +55 -0
- package/src/py/rdb/files/__name__/create_db_user_handler.py.template +97 -0
- package/src/py/rdb/files/__name__/migration_handler.py.template +36 -0
- package/src/py/rdb/files/__name__/models/__init__.py.template +3 -0
- package/src/py/rdb/files/__name__/models/example.py.template +8 -0
- package/src/py/rdb/files/__name__/utils.py.template +104 -0
- package/src/py/rdb/files/alembic.ini.template +38 -0
- package/src/py/rdb/files/config.json.template +14 -0
- package/src/py/rdb/files/migrations/env.py.template +80 -0
- package/src/py/rdb/files/migrations/script.py.mako.template +28 -0
- package/src/py/rdb/generator.d.ts +6 -0
- package/src/py/rdb/generator.js +263 -0
- package/src/py/rdb/generator.js.map +1 -0
- package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +101 -0
- package/src/py/rdb/mcp-server-connection/generator.d.ts +10 -0
- package/src/py/rdb/mcp-server-connection/generator.js +46 -0
- package/src/py/rdb/mcp-server-connection/generator.js.map +1 -0
- package/src/py/rdb/mcp-server-connection/schema.d.js +8 -0
- package/src/py/rdb/mcp-server-connection/schema.d.js.map +1 -0
- package/src/py/rdb/mcp-server-connection/schema.d.ts +15 -0
- package/src/py/rdb/mcp-server-connection/schema.json +27 -0
- package/src/py/rdb/schema.d.js +6 -0
- package/src/py/rdb/schema.d.js.map +1 -0
- package/src/py/rdb/schema.d.ts +16 -0
- package/src/py/rdb/schema.json +77 -0
- package/src/py/rdb/utils.d.ts +6 -0
- package/src/py/rdb/utils.js +16 -0
- package/src/py/rdb/utils.js.map +1 -0
- package/src/sdk/py.d.ts +2 -0
- package/src/sdk/py.js +1 -0
- package/src/sdk/py.js.map +1 -1
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +7 -7
- package/src/smithy/ts/api/files/handler.ts.template +2 -2
- package/src/smithy/ts/api/files/local-server.ts.template +2 -2
- package/src/smithy/ts/api/files/operations/echo.ts.template +2 -2
- package/src/smithy/ts/api/files/service.ts.template +3 -3
- package/src/smithy/ts/api/generator.js +3 -1
- package/src/smithy/ts/api/generator.js.map +1 -1
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +12 -12
- package/src/trpc/backend/files/src/client/index.ts.template +1 -1
- package/src/trpc/backend/files/src/handler.ts.template +1 -1
- package/src/trpc/backend/files/src/index.ts.template +5 -5
- package/src/trpc/backend/files/src/init.ts.template +1 -1
- package/src/trpc/backend/files/src/local-server.ts.template +1 -1
- package/src/trpc/backend/files/src/middleware/index.ts.template +7 -7
- package/src/trpc/backend/files/src/procedures/echo.ts.template +2 -2
- package/src/trpc/backend/files/src/router.ts.template +2 -2
- package/src/trpc/backend/files/src/schema/index.ts.template +1 -1
- package/src/trpc/backend/generator.js +3 -1
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/ts/agent/__snapshots__/generator.spec.ts.snap +89 -3
- package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client-strands.ts.template +2 -2
- package/src/ts/agent/a2a-connection/generator.js +3 -1
- package/src/ts/agent/a2a-connection/generator.js.map +1 -1
- package/src/ts/agent/files/a2a/index.ts.template +1 -1
- package/src/ts/agent/files/ag-ui/index.ts.template +1 -1
- package/src/ts/agent/files/http/client.ts.template +2 -2
- package/src/ts/agent/files/http/index.ts.template +2 -2
- package/src/ts/agent/files/http/router.ts.template +3 -3
- package/src/ts/agent/gateway-connection/files/agent-connection/app/__gatewayKebabCase__-client-strands.ts.template +2 -2
- package/src/ts/agent/gateway-connection/generator.js +3 -1
- package/src/ts/agent/gateway-connection/generator.js.map +1 -1
- package/src/ts/agent/generator.js +5 -2
- package/src/ts/agent/generator.js.map +1 -1
- package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client-strands.ts.template +2 -2
- package/src/ts/agent/mcp-connection/generator.js +3 -1
- package/src/ts/agent/mcp-connection/generator.js.map +1 -1
- package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +3 -2
- package/src/ts/astro-docs/generator.js +2 -0
- package/src/ts/astro-docs/generator.js.map +1 -1
- package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/dynamodb/files/src/client.ts.template +5 -2
- package/src/ts/dynamodb/files/src/entities/example.ts.template +1 -1
- package/src/ts/dynamodb/files/src/entities/index.ts.template +1 -1
- package/src/ts/dynamodb/files/src/index.ts.template +2 -2
- package/src/ts/dynamodb/generator.js +3 -1
- package/src/ts/dynamodb/generator.js.map +1 -1
- package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/lib/generator.js +7 -1
- package/src/ts/lib/generator.js.map +1 -1
- package/src/ts/lib/ts-project-utils.js +19 -4
- package/src/ts/lib/ts-project-utils.js.map +1 -1
- package/src/ts/lib/types.d.ts +6 -0
- package/src/ts/lib/types.js.map +1 -1
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +94 -8
- package/src/ts/mcp-server/generator.js +3 -2
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/nx-generator/files/local/generator.ts.template +2 -2
- package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.ts.template +2 -2
- package/src/ts/nx-generator/generator.js +5 -2
- package/src/ts/nx-generator/generator.js.map +1 -1
- package/src/ts/nx-plugin/files/mcp-server/server.ts.template +5 -5
- package/src/ts/nx-plugin/files/mcp-server/tools/create-workspace-command.ts.template +2 -2
- package/src/ts/nx-plugin/files/mcp-server/tools/general-guidance.ts.template +1 -1
- package/src/ts/nx-plugin/files/mcp-server/tools/generator-guide.ts.template +2 -2
- package/src/ts/nx-plugin/files/mcp-server/tools/list-generators.ts.template +2 -2
- package/src/ts/nx-plugin/files/mcp-server/utils.ts.template +3 -3
- package/src/ts/nx-plugin/generator.js +3 -1
- package/src/ts/nx-plugin/generator.js.map +1 -1
- package/src/ts/nx-plugin/utils.js +7 -4
- package/src/ts/nx-plugin/utils.js.map +1 -1
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +149 -177
- package/src/ts/rdb/files/src/create-db-user-handler.ts.template +2 -2
- package/src/ts/rdb/files/src/index.ts.template +1 -1
- package/src/ts/rdb/files/src/migration-handler.ts.template +1 -1
- package/src/ts/rdb/files/src/prisma.ts.template +7 -4
- package/src/ts/rdb/generator.js +7 -4
- package/src/ts/rdb/generator.js.map +1 -1
- package/src/ts/rdb/schema.json +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +45 -45
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +2 -2
- package/src/utils/agent-chat/agent-chat.js +3 -1
- package/src/utils/agent-chat/agent-chat.js.map +1 -1
- package/src/utils/agent-chat/files/a2a/chat.ts.template +1 -1
- package/src/utils/agent-chat/files/ag-ui/chat.ts.template +1 -1
- package/src/utils/agent-chat/files/http-py/chat.ts.template +2 -2
- package/src/utils/agent-chat/files/http-ts/chat.ts.template +1 -1
- package/src/utils/agent-connection/agent-connection.js +4 -1
- package/src/utils/agent-connection/agent-connection.js.map +1 -1
- package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +2 -2
- package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +1 -1
- package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +2 -2
- package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +2 -2
- package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +1 -1
- package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +1 -1
- package/src/utils/agent-connection/files/core-strands/base/with-session-id-strands.ts.template +1 -1
- package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +1 -1
- package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +1 -1
- package/src/utils/agent-core-constructs/agent-core-constructs.js +10 -3
- package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
- package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +3 -3
- package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +4 -4
- package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +1 -1
- package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +27 -0
- package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +60 -1
- package/src/utils/api-constructs/api-constructs.js +8 -2
- package/src/utils/api-constructs/api-constructs.js.map +1 -1
- package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +8 -8
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +8 -8
- package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +3 -3
- package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account/index.js.template +32 -20
- package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +1 -1
- package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +4 -4
- package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +1 -1
- package/src/utils/ast.js +16 -0
- package/src/utils/ast.js.map +1 -1
- package/src/utils/commands.d.ts +1 -1
- package/src/utils/commands.js +4 -1
- package/src/utils/commands.js.map +1 -1
- package/src/utils/dynamodb-constructs/dynamodb-constructs.js +9 -2
- package/src/utils/dynamodb-constructs/dynamodb-constructs.js.map +1 -1
- package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +3 -3
- package/src/utils/dynamodb-constructs/files/cdk/core/dynamodb.ts.template +1 -1
- package/src/utils/files/common/constructs/src/core/index.ts.template +4 -4
- package/src/utils/files/common/constructs/src/index.ts.template +2 -2
- package/src/utils/files/common/infra-config/src/index.ts.template +3 -3
- package/src/utils/files/common/infra-config/src/resolve-stage.ts.template +2 -2
- package/src/utils/files/common/infra-config/src/stages.config.ts.template +1 -1
- package/src/utils/files/common/scripts/src/infra/infra-deploy.ts.template +1 -1
- package/src/utils/files/common/scripts/src/infra/infra-destroy.ts.template +1 -1
- package/src/utils/files/common/scripts/src/infra/stage-credentials/run.ts.template +3 -3
- package/src/utils/files/common/shadcn/src/index.ts.template +2 -2
- package/src/utils/function-constructs/files/cdk/app/lambda-functions/__nameKebabCase__.ts.template +1 -1
- package/src/utils/function-constructs/function-constructs.js +3 -1
- package/src/utils/function-constructs/function-constructs.js.map +1 -1
- package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +2 -2
- package/src/utils/identity-constructs/identity-constructs.js +5 -1
- package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
- package/src/utils/module-format.d.ts +28 -0
- package/src/utils/module-format.js +28 -0
- package/src/utils/module-format.js.map +1 -0
- package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +61 -17
- package/src/utils/rdb-constructs/files/cdk/core/rdb/aurora.ts.template +68 -78
- package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +88 -8
- package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +5 -32
- package/src/utils/rdb-constructs/rdb-constructs.d.ts +11 -1
- package/src/utils/rdb-constructs/rdb-constructs.js +9 -2
- package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
- package/src/utils/shared-constructs.js +12 -22
- package/src/utils/shared-constructs.js.map +1 -1
- package/src/utils/shared-infra-config.js +3 -1
- package/src/utils/shared-infra-config.js.map +1 -1
- package/src/utils/shared-infra-scripts.js +3 -1
- package/src/utils/shared-infra-scripts.js.map +1 -1
- package/src/utils/shared-rdb-scripts.js +5 -1
- package/src/utils/shared-rdb-scripts.js.map +1 -1
- package/src/utils/shared-shadcn.js +3 -1
- package/src/utils/shared-shadcn.js.map +1 -1
- package/src/utils/test.d.ts +2 -0
- package/src/utils/test.js +7 -1
- package/src/utils/test.js.map +1 -1
- package/src/utils/versions.d.ts +73 -69
- package/src/utils/versions.js +71 -67
- package/src/utils/versions.js.map +1 -1
- package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +2 -2
- package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +2 -2
- package/src/utils/website-constructs/website-constructs.js +9 -2
- package/src/utils/website-constructs/website-constructs.js.map +1 -1
- 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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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)}
|
|
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)}
|
|
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 = (
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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;
|
|
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
|
|
44
|
+
} from './types.gen<% if (esm) { %>.js<% } %>';
|
|
45
45
|
<%_ } _%>
|
|
46
|
-
import { <%- className %> } from './client.gen
|
|
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,
|
|
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,
|
|
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':
|