@aws/nx-plugin 1.0.0-rc.57 → 1.0.0-rc.59
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 +2917 -1295
- package/generators.json +17 -1
- package/migrations.json +36 -26
- package/package.json +13 -13
- package/src/agentcore-gateway/__snapshots__/generator.spec.ts.snap +273 -0
- package/src/agentcore-gateway/agent-connection/generator.d.ts +19 -0
- package/src/agentcore-gateway/agent-connection/generator.js +90 -0
- package/src/agentcore-gateway/agent-connection/generator.js.map +1 -0
- package/src/agentcore-gateway/agent-connection/schema.d.js +6 -0
- package/src/agentcore-gateway/agent-connection/schema.d.js.map +1 -0
- package/src/agentcore-gateway/agent-connection/schema.d.ts +13 -0
- package/src/agentcore-gateway/agent-connection/schema.json +31 -0
- package/src/agentcore-gateway/attach-upstream.d.ts +16 -0
- package/src/agentcore-gateway/attach-upstream.js +32 -11
- package/src/agentcore-gateway/attach-upstream.js.map +1 -1
- package/src/agentcore-gateway/files/project/http/local-dev.ts.template +77 -0
- package/src/agentcore-gateway/generator.d.ts +17 -1
- package/src/agentcore-gateway/generator.js +25 -12
- package/src/agentcore-gateway/generator.js.map +1 -1
- package/src/agentcore-gateway/react-connection/__snapshots__/generator.spec.ts.snap +68 -0
- package/src/agentcore-gateway/react-connection/generator.d.ts +19 -0
- package/src/agentcore-gateway/react-connection/generator.js +119 -0
- package/src/agentcore-gateway/react-connection/generator.js.map +1 -0
- package/src/agentcore-gateway/react-connection/schema.d.js +6 -0
- package/src/agentcore-gateway/react-connection/schema.d.js.map +1 -0
- package/src/agentcore-gateway/react-connection/schema.d.ts +13 -0
- package/src/agentcore-gateway/react-connection/schema.json +31 -0
- package/src/agentcore-gateway/schema.d.js.map +1 -1
- package/src/agentcore-gateway/schema.d.ts +1 -1
- package/src/agentcore-gateway/schema.json +3 -2
- package/src/connection/agent-local-dev.d.ts +16 -0
- package/src/connection/agent-local-dev.js +44 -2
- package/src/connection/agent-local-dev.js.map +1 -1
- package/src/connection/gateway-runtime-config.d.ts +19 -0
- package/src/connection/gateway-runtime-config.js +47 -0
- package/src/connection/gateway-runtime-config.js.map +1 -0
- package/src/connection/generator.js +5 -0
- package/src/connection/generator.js.map +1 -1
- package/src/connection/scaffold-catalog.d.ts +267 -0
- package/src/connection/scaffold-catalog.js +347 -0
- package/src/connection/scaffold-catalog.js.map +1 -0
- package/src/connection/schema-resolver.d.ts +5 -0
- package/src/connection/schema-resolver.js +27 -0
- package/src/connection/schema-resolver.js.map +1 -0
- package/src/connection/supported-connections.d.ts +9 -0
- package/src/connection/supported-connections.js +12 -0
- package/src/connection/supported-connections.js.map +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +7 -7
- package/src/internal/test-matrix/generator.js +39 -1
- package/src/internal/test-matrix/generator.js.map +1 -1
- package/src/migrations/latest/gateway-agent-targets/__snapshots__/migration.spec.ts.snap +223 -0
- package/src/migrations/latest/gateway-agent-targets/metadata.json +3 -0
- package/src/migrations/latest/gateway-agent-targets/migration.js +217 -0
- package/src/migrations/latest/gateway-agent-targets/migration.js.map +1 -0
- package/src/migrations/latest/smithy-ssdk-bundle-pins/metadata.json +3 -0
- package/src/migrations/latest/smithy-ssdk-bundle-pins/migration.js +78 -0
- package/src/migrations/latest/smithy-ssdk-bundle-pins/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.50/modernize-function-props-cast/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.50/modernize-function-props-cast/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.50/restrict-cors-to-custom-domains/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.50/restrict-cors-to-custom-domains/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.50/terraform-bootstrap-adopt-existing-bucket/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.50/terraform-bootstrap-adopt-existing-bucket/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.52/user-identity-waf-allow-localhost-callback/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.52/user-identity-waf-allow-localhost-callback/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.54/order-access-log-delivery-after-bucket-policy/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.54/order-access-log-delivery-after-bucket-policy/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.55/backfill-generator-metadata/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.55/backfill-generator-metadata/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.56/dynamodb-local-remove-optimize-flag/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.56/dynamodb-local-remove-optimize-flag/migration.d.ts +6 -0
- package/src/migrations/v1.0.0-rc.56/dynamodb-local-remove-optimize-flag/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.57/ts-agent-session-management-support/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.57/ts-agent-session-management-support/migration.d.ts +6 -0
- package/src/migrations/v1.0.0-rc.57/ts-agent-session-management-support/migration.js.map +1 -0
- package/src/preset/__snapshots__/generator.spec.ts.snap +5 -5
- package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +10 -8
- package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +8 -8
- package/src/py/agent/__snapshots__/generator.protocols.spec.ts.snap +2 -2
- package/src/py/agent/a2a-connection/generator.d.ts +1 -1
- package/src/py/agent/gateway-connection/generator.d.ts +1 -1
- package/src/py/agent/mcp-connection/generator.d.ts +1 -1
- package/src/py/agent/react-connection/generator.d.ts +4 -1
- package/src/py/agent/react-connection/generator.js +35 -14
- package/src/py/agent/react-connection/generator.js.map +1 -1
- package/src/py/agent/schema.json +1 -0
- package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/dynamodb/schema.json +1 -0
- package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +12 -12
- package/src/py/fast-api/generator.d.ts +5 -0
- package/src/py/fast-api/generator.js +3 -2
- package/src/py/fast-api/generator.js.map +1 -1
- package/src/py/fast-api/schema.json +1 -0
- package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +5 -5
- package/src/py/mcp-server/schema.json +1 -0
- package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/rdb/schema.json +1 -0
- package/src/smithy/project/__snapshots__/generator.spec.ts.snap +4 -4
- package/src/smithy/project/files/service/build.Dockerfile.template +2 -2
- package/src/smithy/project/generator.d.ts +25 -0
- package/src/smithy/project/generator.js +24 -3
- package/src/smithy/project/generator.js.map +1 -1
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +7 -7
- package/src/smithy/ts/api/generator.d.ts +6 -1
- package/src/smithy/ts/api/generator.js +3 -2
- package/src/smithy/ts/api/generator.js.map +1 -1
- package/src/smithy/ts/api/schema.json +1 -0
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +12 -12
- package/src/trpc/backend/generator.d.ts +6 -1
- package/src/trpc/backend/generator.js +3 -2
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/backend/schema.json +1 -0
- package/src/ts/agent/__snapshots__/generator.spec.ts.snap +9 -5
- package/src/ts/agent/generator.d.ts +32 -1
- package/src/ts/agent/generator.js +7 -4
- package/src/ts/agent/generator.js.map +1 -1
- package/src/ts/agent/react-connection/generator.d.ts +16 -1
- package/src/ts/agent/react-connection/generator.js +21 -8
- package/src/ts/agent/react-connection/generator.js.map +1 -1
- package/src/ts/agent/schema.json +1 -0
- package/src/ts/dcr-proxy/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/dynamodb/schema.json +1 -0
- package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/mcp-server/generator.d.ts +32 -1
- package/src/ts/mcp-server/generator.js +7 -4
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/mcp-server/schema.json +1 -0
- package/src/ts/nx-migration/generator.js +40 -27
- package/src/ts/nx-migration/generator.js.map +1 -1
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +6 -6
- package/src/ts/rdb/generator.d.ts +8 -0
- package/src/ts/rdb/generator.js +3 -2
- package/src/ts/rdb/generator.js.map +1 -1
- package/src/ts/rdb/schema.json +1 -0
- package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +16 -0
- package/src/ts/react-website/agui/generator.d.ts +11 -0
- package/src/ts/react-website/agui/generator.js +11 -7
- package/src/ts/react-website/agui/generator.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +61 -45
- package/src/ts/react-website/app/generator.d.ts +6 -1
- package/src/ts/react-website/app/generator.js +3 -2
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/ts/react-website/app/schema.json +1 -0
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +2 -2
- package/src/ts/react-website/cognito-auth/generator.d.ts +6 -1
- package/src/ts/react-website/cognito-auth/generator.js +3 -2
- package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
- package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +23 -0
- package/src/utils/agent-core-constructs/agent-core-constructs.js +24 -1
- 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 -0
- package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +6 -4
- package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +119 -3
- package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +17 -0
- package/src/utils/api-constructs/api-constructs.d.ts +9 -0
- package/src/utils/api-constructs/api-constructs.js +11 -1
- package/src/utils/api-constructs/api-constructs.js.map +1 -1
- package/src/utils/config/utils.d.ts +5 -0
- package/src/utils/config/utils.js +7 -1
- package/src/utils/config/utils.js.map +1 -1
- package/src/utils/connection/open-api/files/components/__apiNameClassName__Provider.tsx.template +13 -2
- package/src/utils/connection/open-api/react.d.ts +10 -1
- package/src/utils/connection/open-api/react.js +3 -2
- package/src/utils/connection/open-api/react.js.map +1 -1
- package/src/utils/docker.d.ts +27 -2
- package/src/utils/docker.js +31 -2
- package/src/utils/docker.js.map +1 -1
- package/src/utils/identity-constructs/identity-constructs.d.ts +10 -0
- package/src/utils/identity-constructs/identity-constructs.js +11 -1
- package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
- package/src/utils/migration-manifest.d.ts +58 -0
- package/src/utils/migration-manifest.js +76 -0
- package/src/utils/migration-manifest.js.map +1 -0
- package/src/utils/migration-versions.d.ts +2 -0
- package/src/utils/migration-versions.js.map +1 -1
- package/src/utils/shared-constructs-constants.d.ts +6 -0
- package/src/utils/shared-constructs-constants.js +5 -0
- package/src/utils/shared-constructs-constants.js.map +1 -1
- package/src/utils/version-upgrade-migration/owned-dependencies.d.ts +26 -0
- package/src/utils/version-upgrade-migration/owned-dependencies.js +52 -4
- package/src/utils/version-upgrade-migration/owned-dependencies.js.map +1 -1
- package/src/utils/version-upgrade-migration/register.d.ts +9 -3
- package/src/utils/version-upgrade-migration/register.js +18 -14
- package/src/utils/version-upgrade-migration/register.js.map +1 -1
- package/src/utils/version-upgrade-migration/sync-embedded-versions.d.ts +26 -0
- package/src/utils/version-upgrade-migration/sync-embedded-versions.js +304 -0
- package/src/utils/version-upgrade-migration/sync-embedded-versions.js.map +1 -0
- package/src/utils/version-upgrade-migration/sync-vended-versions.js +14 -0
- package/src/utils/version-upgrade-migration/sync-vended-versions.js.map +1 -1
- package/src/utils/versions.d.ts +90 -77
- package/src/utils/versions.js +86 -75
- package/src/utils/versions.js.map +1 -1
- package/src/utils/website-constructs/website-constructs.d.ts +11 -0
- package/src/utils/website-constructs/website-constructs.js +12 -1
- package/src/utils/website-constructs/website-constructs.js.map +1 -1
- package/src/migrations/latest/backfill-generator-metadata/migration.js.map +0 -1
- package/src/migrations/latest/dynamodb-local-remove-optimize-flag/migration.js.map +0 -1
- package/src/migrations/latest/modernize-function-props-cast/migration.js.map +0 -1
- package/src/migrations/latest/order-access-log-delivery-after-bucket-policy/migration.js.map +0 -1
- package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js.map +0 -1
- package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js.map +0 -1
- package/src/migrations/latest/ts-agent-session-management-support/migration.js.map +0 -1
- package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.js.map +0 -1
- /package/src/agentcore-gateway/files/project/{local-dev.ts.template → mcp/local-dev.ts.template} +0 -0
- /package/src/migrations/latest/{dynamodb-local-remove-optimize-flag → gateway-agent-targets}/migration.d.ts +0 -0
- /package/src/migrations/latest/{modernize-function-props-cast → smithy-ssdk-bundle-pins}/migration.d.ts +0 -0
- /package/src/migrations/{latest/restrict-cors-to-custom-domains → v1.0.0-rc.50/modernize-function-props-cast}/migration.d.ts +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.50}/modernize-function-props-cast/migration.js +0 -0
- /package/src/migrations/{latest/terraform-bootstrap-adopt-existing-bucket → v1.0.0-rc.50/restrict-cors-to-custom-domains}/migration.d.ts +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.50}/restrict-cors-to-custom-domains/migration.js +0 -0
- /package/src/migrations/{latest/ts-agent-session-management-support → v1.0.0-rc.50/terraform-bootstrap-adopt-existing-bucket}/migration.d.ts +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.50}/terraform-bootstrap-adopt-existing-bucket/migration.js +0 -0
- /package/src/migrations/{latest/order-access-log-delivery-after-bucket-policy → v1.0.0-rc.52/user-identity-waf-allow-localhost-callback}/migration.d.ts +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.52}/user-identity-waf-allow-localhost-callback/migration.js +0 -0
- /package/src/migrations/{latest/user-identity-waf-allow-localhost-callback → v1.0.0-rc.54/order-access-log-delivery-after-bucket-policy}/migration.d.ts +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.54}/order-access-log-delivery-after-bucket-policy/migration.js +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.55}/backfill-generator-metadata/migration.d.ts +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.55}/backfill-generator-metadata/migration.js +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.56}/dynamodb-local-remove-optimize-flag/migration.js +0 -0
- /package/src/migrations/{latest → v1.0.0-rc.57}/ts-agent-session-management-support/migration.js +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`gateway-agent-targets migration > should add the agentName member to vended agent constructs 1`] = `
|
|
4
|
+
"import {
|
|
5
|
+
AgentRuntimeArtifact,
|
|
6
|
+
ProtocolType,
|
|
7
|
+
Runtime,
|
|
8
|
+
} from 'aws-cdk-lib/aws-bedrockagentcore';
|
|
9
|
+
import { Construct } from 'constructs';
|
|
10
|
+
|
|
11
|
+
export class MyAgent extends Construct {
|
|
12
|
+
public readonly dockerImage: AgentRuntimeArtifact;
|
|
13
|
+
public readonly agentCoreRuntime: Runtime;
|
|
14
|
+
/** Default Gateway target name for this agent. */
|
|
15
|
+
public readonly agentName = 'my-agent';
|
|
16
|
+
|
|
17
|
+
constructor(scope: Construct, id: string) {
|
|
18
|
+
super(scope, id);
|
|
19
|
+
this.agentCoreRuntime = undefined as any;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
"
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
exports[`gateway-agent-targets migration > should add the protocol prop and agent target methods to the vended gateway construct 1`] = `
|
|
26
|
+
"import * as cdk from 'aws-cdk-lib';
|
|
27
|
+
import * as agentcore from 'aws-cdk-lib/aws-bedrockagentcore';
|
|
28
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
29
|
+
import * as triggers from 'aws-cdk-lib/triggers';
|
|
30
|
+
import * as wafv2 from 'aws-cdk-lib/aws-wafv2';
|
|
31
|
+
import { Construct } from 'constructs';
|
|
32
|
+
|
|
33
|
+
export interface AgentCoreGatewayProps {
|
|
34
|
+
readonly cedarPolicyPath?: string;
|
|
35
|
+
readonly cedarPolicyVariables?: Record<string, string>;
|
|
36
|
+
readonly enableWaf?: boolean;
|
|
37
|
+
readonly authorizer?: agentcore.IGatewayAuthorizerConfig;
|
|
38
|
+
/**
|
|
39
|
+
* The gateway's protocol. An \`mcp\` gateway aggregates MCP server targets
|
|
40
|
+
* into a single MCP endpoint. An \`http\` gateway has no protocol type and
|
|
41
|
+
* proxies requests to AgentCore Runtime targets via path-based routing
|
|
42
|
+
* (\`/<targetName>/invocations\`) — the target type AgentCore only allows on
|
|
43
|
+
* gateways without a protocol type.
|
|
44
|
+
*
|
|
45
|
+
* @default 'mcp'
|
|
46
|
+
*/
|
|
47
|
+
readonly protocol?: 'mcp' | 'http';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class AgentCoreGateway extends Construct implements iam.IGrantable {
|
|
51
|
+
public readonly gateway: agentcore.Gateway;
|
|
52
|
+
public readonly policyEngine?: agentcore.CfnPolicyEngine;
|
|
53
|
+
public readonly webAcl?: wafv2.CfnWebACL;
|
|
54
|
+
private readonly policies: agentcore.CfnPolicy[] = [];
|
|
55
|
+
private targetReadinessProbe?: triggers.TriggerFunction;
|
|
56
|
+
private readonly targetRuntimeArns: string[] = [];
|
|
57
|
+
private readonly protocol: 'mcp' | 'http';
|
|
58
|
+
|
|
59
|
+
constructor(scope: Construct, id: string, props?: AgentCoreGatewayProps) {
|
|
60
|
+
super(scope, id);
|
|
61
|
+
|
|
62
|
+
this.protocol = props?.protocol ?? 'mcp';
|
|
63
|
+
|
|
64
|
+
this.gateway = new agentcore.Gateway(this, 'Gateway', {
|
|
65
|
+
gatewayName: cdk.Names.uniqueResourceName(this, { maxLength: 39 }),
|
|
66
|
+
protocolConfiguration: new agentcore.McpProtocolConfiguration({
|
|
67
|
+
searchType: agentcore.McpGatewaySearchType.SEMANTIC,
|
|
68
|
+
supportedVersions: [agentcore.MCPProtocolVersion.MCP_2025_03_26],
|
|
69
|
+
}),
|
|
70
|
+
authorizerConfiguration:
|
|
71
|
+
props?.authorizer ?? agentcore.GatewayAuthorizer.usingAwsIam(),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (this.protocol === 'http') {
|
|
75
|
+
// AgentCore Runtime targets require a gateway without a protocol type,
|
|
76
|
+
// which the Gateway L2 cannot express — it always renders MCP — so
|
|
77
|
+
// remove the protocol from the underlying CloudFormation resource.
|
|
78
|
+
const cfnGateway = this.gateway.node.defaultChild as agentcore.CfnGateway;
|
|
79
|
+
cfnGateway.addPropertyDeletionOverride('ProtocolType');
|
|
80
|
+
cfnGateway.addPropertyDeletionOverride('ProtocolConfiguration');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public get grantPrincipal(): iam.IPrincipal {
|
|
85
|
+
return this.gateway.role.grantPrincipal;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public addGatewayTarget(props: {
|
|
89
|
+
gatewayTargetName: string;
|
|
90
|
+
gatewayUrl: string;
|
|
91
|
+
gatewayArn: string;
|
|
92
|
+
}): agentcore.CfnGatewayTarget {
|
|
93
|
+
const target = this.addTarget(props.gatewayTargetName, props.gatewayUrl);
|
|
94
|
+
|
|
95
|
+
const grant = this.gateway.role.addToPrincipalPolicy(
|
|
96
|
+
new iam.PolicyStatement({
|
|
97
|
+
actions: ['bedrock-agentcore:InvokeGateway'],
|
|
98
|
+
resources: [props.gatewayArn],
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
101
|
+
if (grant.policyDependable) {
|
|
102
|
+
target.node.addDependency(grant.policyDependable);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return target;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Add an agent runtime construct as a target of this Gateway. Requires the
|
|
110
|
+
* \`http\` protocol — the gateway proxies requests for the agent under
|
|
111
|
+
* \`<gatewayUrl>/<targetName>/invocations\`, without protocol translation.
|
|
112
|
+
*
|
|
113
|
+
* The target name defaults to the agent construct's \`agentName\` (its
|
|
114
|
+
* project's class name in kebab-case, e.g. \`MyAgent\` -> \`my-agent\`). It
|
|
115
|
+
* forms the target's invocation path, so renaming it later is a breaking
|
|
116
|
+
* change for consumers.
|
|
117
|
+
*/
|
|
118
|
+
public addAgent(
|
|
119
|
+
agent: Construct & {
|
|
120
|
+
readonly agentCoreRuntime: agentcore.Runtime;
|
|
121
|
+
readonly agentName: string;
|
|
122
|
+
},
|
|
123
|
+
props?: {
|
|
124
|
+
gatewayTargetName?: string;
|
|
125
|
+
},
|
|
126
|
+
): agentcore.CfnGatewayTarget {
|
|
127
|
+
return this.addAgentTarget({
|
|
128
|
+
gatewayTargetName: props?.gatewayTargetName ?? agent.agentName,
|
|
129
|
+
agentRuntimeArn: agent.agentCoreRuntime.agentRuntimeArn,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Register an agent runtime ARN as a Gateway target. Prefer
|
|
135
|
+
* {@link addAgent} when the construct is in scope.
|
|
136
|
+
*/
|
|
137
|
+
public addAgentTarget(props: {
|
|
138
|
+
gatewayTargetName: string;
|
|
139
|
+
agentRuntimeArn: string;
|
|
140
|
+
}): agentcore.CfnGatewayTarget {
|
|
141
|
+
if (this.protocol !== 'http') {
|
|
142
|
+
throw new Error(
|
|
143
|
+
\`Agent runtime targets require an http-protocol gateway, but this gateway uses '\${this.protocol}'.\`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// The construct id is derived from the target name so the two change
|
|
148
|
+
// together — target names are unique per gateway, and replacing a target
|
|
149
|
+
// under an unchanged name fails with AlreadyExists.
|
|
150
|
+
const target = new agentcore.CfnGatewayTarget(
|
|
151
|
+
this,
|
|
152
|
+
\`Target-\${props.gatewayTargetName}\`,
|
|
153
|
+
{
|
|
154
|
+
gatewayIdentifier: this.gateway.gatewayId,
|
|
155
|
+
name: props.gatewayTargetName,
|
|
156
|
+
targetConfiguration: {
|
|
157
|
+
http: {
|
|
158
|
+
agentcoreRuntime: {
|
|
159
|
+
arn: props.agentRuntimeArn,
|
|
160
|
+
qualifier: 'DEFAULT',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
// The bare gateway IAM role credential: runtime targets reject the
|
|
165
|
+
// iamCredentialProvider detail MCP targets carry.
|
|
166
|
+
credentialProviderConfigurations: [
|
|
167
|
+
{
|
|
168
|
+
credentialProviderType: 'GATEWAY_IAM_ROLE',
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
// Grant the gateway role invoke access to the target runtime before the
|
|
175
|
+
// target is created — AgentCore validates access to the runtime during
|
|
176
|
+
// target creation.
|
|
177
|
+
const grant = this.gateway.role.addToPrincipalPolicy(
|
|
178
|
+
new iam.PolicyStatement({
|
|
179
|
+
actions: [
|
|
180
|
+
'bedrock-agentcore:InvokeAgentRuntime',
|
|
181
|
+
'bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream',
|
|
182
|
+
// A2A targets additionally serve their agent card via the gateway.
|
|
183
|
+
'bedrock-agentcore:GetAgentCard',
|
|
184
|
+
],
|
|
185
|
+
resources: [props.agentRuntimeArn, \`\${props.agentRuntimeArn}/*\`],
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
188
|
+
if (grant.policyDependable) {
|
|
189
|
+
target.node.addDependency(grant.policyDependable);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return target;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private addTarget(
|
|
196
|
+
gatewayTargetName: string,
|
|
197
|
+
endpoint: string,
|
|
198
|
+
): agentcore.CfnGatewayTarget {
|
|
199
|
+
const target = new agentcore.CfnGatewayTarget(
|
|
200
|
+
this,
|
|
201
|
+
\`Target-\${gatewayTargetName}\`,
|
|
202
|
+
{
|
|
203
|
+
gatewayIdentifier: this.gateway.gatewayId,
|
|
204
|
+
name: gatewayTargetName,
|
|
205
|
+
targetConfiguration: {
|
|
206
|
+
mcp: {
|
|
207
|
+
mcpServer: {
|
|
208
|
+
endpoint,
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
for (const policy of this.policies) {
|
|
216
|
+
policy.node.addDependency(target);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return target;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
"
|
|
223
|
+
`;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { applyGritQL, GRIT_INSERT_PLACEHOLDER, insertViaGritQL, matchGritQL } from "../../../utils/ast.js";
|
|
5
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
6
|
+
import { PACKAGES_DIR, SHARED_CONSTRUCTS_DIR } from "../../../utils/shared-constructs-constants.js";
|
|
7
|
+
/**
|
|
8
|
+
* Bring existing workspaces up to the generators' current gateway-target
|
|
9
|
+
* support, so agents can be attached to an http-protocol AgentCore Gateway:
|
|
10
|
+
*
|
|
11
|
+
* - The vended `AgentCoreGateway` core construct gains the `protocol` prop
|
|
12
|
+
* (http gateways have no protocol type, which AgentCore Runtime targets
|
|
13
|
+
* require) and the `addAgent` / `addAgentTarget` methods.
|
|
14
|
+
* - Vended agent constructs gain the `agentName` member `addAgent` reads as
|
|
15
|
+
* the default gateway target name.
|
|
16
|
+
*
|
|
17
|
+
* Both files are generated with `KeepExisting`, so without this an upgraded
|
|
18
|
+
* workspace pairs new app-level constructs with stale core ones.
|
|
19
|
+
*/ const GATEWAY_CONSTRUCT_FILE = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/core/agentcore-gateway/agentcore-gateway.ts`;
|
|
20
|
+
const AGENTS_DIR = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/app/agents`;
|
|
21
|
+
const PROTOCOL_PROP = `/**
|
|
22
|
+
* The gateway's protocol. An \`mcp\` gateway aggregates MCP server targets
|
|
23
|
+
* into a single MCP endpoint. An \`http\` gateway has no protocol type and
|
|
24
|
+
* proxies requests to AgentCore Runtime targets via path-based routing
|
|
25
|
+
* (\`/<targetName>/invocations\`) — the target type AgentCore only allows on
|
|
26
|
+
* gateways without a protocol type.
|
|
27
|
+
*
|
|
28
|
+
* @default 'mcp'
|
|
29
|
+
*/
|
|
30
|
+
readonly protocol?: 'mcp' | 'http';`;
|
|
31
|
+
const PROTOCOL_CONSTRUCTOR_STATEMENTS = `this.protocol = props?.protocol ?? 'mcp';
|
|
32
|
+
`;
|
|
33
|
+
const PROTOCOL_TYPE_REMOVAL = `
|
|
34
|
+
if (this.protocol === 'http') {
|
|
35
|
+
// AgentCore Runtime targets require a gateway without a protocol type,
|
|
36
|
+
// which the Gateway L2 cannot express — it always renders MCP — so
|
|
37
|
+
// remove the protocol from the underlying CloudFormation resource.
|
|
38
|
+
const cfnGateway = this.gateway.node.defaultChild as agentcore.CfnGateway;
|
|
39
|
+
cfnGateway.addPropertyDeletionOverride('ProtocolType');
|
|
40
|
+
cfnGateway.addPropertyDeletionOverride('ProtocolConfiguration');
|
|
41
|
+
}`;
|
|
42
|
+
const AGENT_TARGET_METHODS = `
|
|
43
|
+
/**
|
|
44
|
+
* Add an agent runtime construct as a target of this Gateway. Requires the
|
|
45
|
+
* \`http\` protocol — the gateway proxies requests for the agent under
|
|
46
|
+
* \`<gatewayUrl>/<targetName>/invocations\`, without protocol translation.
|
|
47
|
+
*
|
|
48
|
+
* The target name defaults to the agent construct's \`agentName\` (its
|
|
49
|
+
* project's class name in kebab-case, e.g. \`MyAgent\` -> \`my-agent\`). It
|
|
50
|
+
* forms the target's invocation path, so renaming it later is a breaking
|
|
51
|
+
* change for consumers.
|
|
52
|
+
*/
|
|
53
|
+
public addAgent(
|
|
54
|
+
agent: Construct & {
|
|
55
|
+
readonly agentCoreRuntime: agentcore.Runtime;
|
|
56
|
+
readonly agentName: string;
|
|
57
|
+
},
|
|
58
|
+
props?: {
|
|
59
|
+
gatewayTargetName?: string;
|
|
60
|
+
},
|
|
61
|
+
): agentcore.CfnGatewayTarget {
|
|
62
|
+
return this.addAgentTarget({
|
|
63
|
+
gatewayTargetName: props?.gatewayTargetName ?? agent.agentName,
|
|
64
|
+
agentRuntimeArn: agent.agentCoreRuntime.agentRuntimeArn,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Register an agent runtime ARN as a Gateway target. Prefer
|
|
70
|
+
* {@link addAgent} when the construct is in scope.
|
|
71
|
+
*/
|
|
72
|
+
public addAgentTarget(props: {
|
|
73
|
+
gatewayTargetName: string;
|
|
74
|
+
agentRuntimeArn: string;
|
|
75
|
+
}): agentcore.CfnGatewayTarget {
|
|
76
|
+
if (this.protocol !== 'http') {
|
|
77
|
+
throw new Error(
|
|
78
|
+
\`Agent runtime targets require an http-protocol gateway, but this gateway uses '\${this.protocol}'.\`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// The construct id is derived from the target name so the two change
|
|
83
|
+
// together — target names are unique per gateway, and replacing a target
|
|
84
|
+
// under an unchanged name fails with AlreadyExists.
|
|
85
|
+
const target = new agentcore.CfnGatewayTarget(
|
|
86
|
+
this,
|
|
87
|
+
\`Target-\${props.gatewayTargetName}\`,
|
|
88
|
+
{
|
|
89
|
+
gatewayIdentifier: this.gateway.gatewayId,
|
|
90
|
+
name: props.gatewayTargetName,
|
|
91
|
+
targetConfiguration: {
|
|
92
|
+
http: {
|
|
93
|
+
agentcoreRuntime: {
|
|
94
|
+
arn: props.agentRuntimeArn,
|
|
95
|
+
qualifier: 'DEFAULT',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
// The bare gateway IAM role credential: runtime targets reject the
|
|
100
|
+
// iamCredentialProvider detail MCP targets carry.
|
|
101
|
+
credentialProviderConfigurations: [
|
|
102
|
+
{
|
|
103
|
+
credentialProviderType: 'GATEWAY_IAM_ROLE',
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Grant the gateway role invoke access to the target runtime before the
|
|
110
|
+
// target is created — AgentCore validates access to the runtime during
|
|
111
|
+
// target creation.
|
|
112
|
+
const grant = this.gateway.role.addToPrincipalPolicy(
|
|
113
|
+
new iam.PolicyStatement({
|
|
114
|
+
actions: [
|
|
115
|
+
'bedrock-agentcore:InvokeAgentRuntime',
|
|
116
|
+
'bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream',
|
|
117
|
+
// A2A targets additionally serve their agent card via the gateway.
|
|
118
|
+
'bedrock-agentcore:GetAgentCard',
|
|
119
|
+
],
|
|
120
|
+
resources: [props.agentRuntimeArn, \`\${props.agentRuntimeArn}/*\`],
|
|
121
|
+
}),
|
|
122
|
+
);
|
|
123
|
+
if (grant.policyDependable) {
|
|
124
|
+
target.node.addDependency(grant.policyDependable);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return target;
|
|
128
|
+
}`;
|
|
129
|
+
/**
|
|
130
|
+
* Add the `protocol` prop, its constructor handling and the agent-target
|
|
131
|
+
* methods to the vended `AgentCoreGateway` core construct.
|
|
132
|
+
*/ const migrateGatewayConstruct = async (tree, nextSteps)=>{
|
|
133
|
+
if (!tree.exists(GATEWAY_CONSTRUCT_FILE)) {
|
|
134
|
+
// No vended gateway construct in this workspace - nothing to migrate.
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if ((tree.read(GATEWAY_CONSTRUCT_FILE, 'utf-8') ?? '').includes('addAgentTarget')) {
|
|
138
|
+
// Already migrated.
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const divergedMessage = `${GATEWAY_CONSTRUCT_FILE}: the AgentCoreGateway construct has diverged from the generated shape - left untouched. Re-run the agentcore-gateway generator in a fresh workspace to see the current construct, which supports agent runtime targets via a 'protocol' prop and addAgent()/addAgentTarget() methods.`;
|
|
142
|
+
// Anchored on the shapes every vended version of the construct carries: the
|
|
143
|
+
// props interface, the class field the protocol field is inserted after,
|
|
144
|
+
// and the Gateway creation in the constructor.
|
|
145
|
+
const hasVendedShape = await matchGritQL(tree, GATEWAY_CONSTRUCT_FILE, '`export interface AgentCoreGatewayProps { $_ }`') && await matchGritQL(tree, GATEWAY_CONSTRUCT_FILE, '`private readonly targetRuntimeArns: string[] = []`') && await matchGritQL(tree, GATEWAY_CONSTRUCT_FILE, "`this.gateway = new agentcore.Gateway(this, 'Gateway', $_)`");
|
|
146
|
+
if (!hasVendedShape) {
|
|
147
|
+
nextSteps.push(divergedMessage);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// 1. The protocol prop on AgentCoreGatewayProps. The placeholder keeps the
|
|
151
|
+
// prop's doc comment (with its backticks) out of the GritQL pattern.
|
|
152
|
+
await insertViaGritQL(tree, GATEWAY_CONSTRUCT_FILE, `\`export interface AgentCoreGatewayProps { $members }\` where {
|
|
153
|
+
$members <: not contains \`protocol\`
|
|
154
|
+
} => \`export interface AgentCoreGatewayProps { $members
|
|
155
|
+
${GRIT_INSERT_PLACEHOLDER}
|
|
156
|
+
}\``, PROTOCOL_PROP);
|
|
157
|
+
// 2. The protocol class field. Matched without the trailing semicolon —
|
|
158
|
+
// GritQL parses the snippet standalone, where the semicolon is not part
|
|
159
|
+
// of the field's AST node.
|
|
160
|
+
await applyGritQL(tree, GATEWAY_CONSTRUCT_FILE, `\`private readonly targetRuntimeArns: string[] = []\` as $field where {
|
|
161
|
+
$program <: not contains \`private readonly protocol\`
|
|
162
|
+
} => \`$field;
|
|
163
|
+
private readonly protocol: 'mcp' | 'http'\``);
|
|
164
|
+
// 3. Assign the field and remove the protocol type for http gateways.
|
|
165
|
+
await insertViaGritQL(tree, GATEWAY_CONSTRUCT_FILE, `\`this.gateway = new agentcore.Gateway($args);\` as $stmt where {
|
|
166
|
+
$program <: not contains \`this.protocol = props\`
|
|
167
|
+
} => \`${GRIT_INSERT_PLACEHOLDER}
|
|
168
|
+
$stmt\``, PROTOCOL_CONSTRUCTOR_STATEMENTS);
|
|
169
|
+
await insertViaGritQL(tree, GATEWAY_CONSTRUCT_FILE, `\`this.gateway = new agentcore.Gateway($args);\` as $stmt where {
|
|
170
|
+
$program <: not contains \`addPropertyDeletionOverride\`
|
|
171
|
+
} => \`$stmt
|
|
172
|
+
${GRIT_INSERT_PLACEHOLDER}\``, PROTOCOL_TYPE_REMOVAL);
|
|
173
|
+
// 4. The agent-target methods, inserted after addGatewayTarget (present in
|
|
174
|
+
// every vended version that also has the readiness probe field).
|
|
175
|
+
const addedMethods = await insertViaGritQL(tree, GATEWAY_CONSTRUCT_FILE, `\`public addGatewayTarget($params): agentcore.CfnGatewayTarget { $body }\` as $method where {
|
|
176
|
+
$program <: not contains \`addAgentTarget\`
|
|
177
|
+
} => \`$method
|
|
178
|
+
${GRIT_INSERT_PLACEHOLDER}\``, AGENT_TARGET_METHODS);
|
|
179
|
+
if (!addedMethods) {
|
|
180
|
+
nextSteps.push(divergedMessage);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Add the `agentName` member to each vended agent construct, which
|
|
186
|
+
* `AgentCoreGateway.addAgent` reads as the default gateway target name.
|
|
187
|
+
*/ const migrateAgentConstructs = async (tree, nextSteps)=>{
|
|
188
|
+
if (!tree.exists(AGENTS_DIR)) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
for (const dir of tree.children(AGENTS_DIR)){
|
|
192
|
+
const constructFile = `${AGENTS_DIR}/${dir}/${dir}.ts`;
|
|
193
|
+
if (!tree.exists(constructFile)) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if ((tree.read(constructFile, 'utf-8') ?? '').includes('agentName')) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const added = await insertViaGritQL(tree, constructFile, `\`public readonly agentCoreRuntime: Runtime\` as $field => \`$field;
|
|
200
|
+
${GRIT_INSERT_PLACEHOLDER}\``, `/** Default Gateway target name for this agent. */
|
|
201
|
+
public readonly agentName = '${dir}'`);
|
|
202
|
+
if (!added) {
|
|
203
|
+
nextSteps.push(`${constructFile}: the agent construct has diverged from the generated shape - left untouched. To attach this agent to a gateway with addAgent(), add a \`public readonly agentName = '${dir}';\` member (or use addAgentTarget() with an explicit target name).`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
export default async function migration(tree) {
|
|
208
|
+
const nextSteps = [];
|
|
209
|
+
await migrateGatewayConstruct(tree, nextSteps);
|
|
210
|
+
await migrateAgentConstructs(tree, nextSteps);
|
|
211
|
+
await formatFilesInSubtree(tree);
|
|
212
|
+
return {
|
|
213
|
+
nextSteps
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/gateway-agent-targets/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { MigrationReturnObject, Tree } from '@nx/devkit';\nimport {\n applyGritQL,\n GRIT_INSERT_PLACEHOLDER,\n insertViaGritQL,\n matchGritQL,\n} from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n} from '../../../utils/shared-constructs-constants';\n\n/**\n * Bring existing workspaces up to the generators' current gateway-target\n * support, so agents can be attached to an http-protocol AgentCore Gateway:\n *\n * - The vended `AgentCoreGateway` core construct gains the `protocol` prop\n * (http gateways have no protocol type, which AgentCore Runtime targets\n * require) and the `addAgent` / `addAgentTarget` methods.\n * - Vended agent constructs gain the `agentName` member `addAgent` reads as\n * the default gateway target name.\n *\n * Both files are generated with `KeepExisting`, so without this an upgraded\n * workspace pairs new app-level constructs with stale core ones.\n */\n\nconst GATEWAY_CONSTRUCT_FILE = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/core/agentcore-gateway/agentcore-gateway.ts`;\n\nconst AGENTS_DIR = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/app/agents`;\n\nconst PROTOCOL_PROP = `/**\n * The gateway's protocol. An \\`mcp\\` gateway aggregates MCP server targets\n * into a single MCP endpoint. An \\`http\\` gateway has no protocol type and\n * proxies requests to AgentCore Runtime targets via path-based routing\n * (\\`/<targetName>/invocations\\`) — the target type AgentCore only allows on\n * gateways without a protocol type.\n *\n * @default 'mcp'\n */\n readonly protocol?: 'mcp' | 'http';`;\n\nconst PROTOCOL_CONSTRUCTOR_STATEMENTS = `this.protocol = props?.protocol ?? 'mcp';\n`;\n\nconst PROTOCOL_TYPE_REMOVAL = `\n if (this.protocol === 'http') {\n // AgentCore Runtime targets require a gateway without a protocol type,\n // which the Gateway L2 cannot express — it always renders MCP — so\n // remove the protocol from the underlying CloudFormation resource.\n const cfnGateway = this.gateway.node.defaultChild as agentcore.CfnGateway;\n cfnGateway.addPropertyDeletionOverride('ProtocolType');\n cfnGateway.addPropertyDeletionOverride('ProtocolConfiguration');\n }`;\n\nconst AGENT_TARGET_METHODS = `\n /**\n * Add an agent runtime construct as a target of this Gateway. Requires the\n * \\`http\\` protocol — the gateway proxies requests for the agent under\n * \\`<gatewayUrl>/<targetName>/invocations\\`, without protocol translation.\n *\n * The target name defaults to the agent construct's \\`agentName\\` (its\n * project's class name in kebab-case, e.g. \\`MyAgent\\` -> \\`my-agent\\`). It\n * forms the target's invocation path, so renaming it later is a breaking\n * change for consumers.\n */\n public addAgent(\n agent: Construct & {\n readonly agentCoreRuntime: agentcore.Runtime;\n readonly agentName: string;\n },\n props?: {\n gatewayTargetName?: string;\n },\n ): agentcore.CfnGatewayTarget {\n return this.addAgentTarget({\n gatewayTargetName: props?.gatewayTargetName ?? agent.agentName,\n agentRuntimeArn: agent.agentCoreRuntime.agentRuntimeArn,\n });\n }\n\n /**\n * Register an agent runtime ARN as a Gateway target. Prefer\n * {@link addAgent} when the construct is in scope.\n */\n public addAgentTarget(props: {\n gatewayTargetName: string;\n agentRuntimeArn: string;\n }): agentcore.CfnGatewayTarget {\n if (this.protocol !== 'http') {\n throw new Error(\n \\`Agent runtime targets require an http-protocol gateway, but this gateway uses '\\${this.protocol}'.\\`,\n );\n }\n\n // The construct id is derived from the target name so the two change\n // together — target names are unique per gateway, and replacing a target\n // under an unchanged name fails with AlreadyExists.\n const target = new agentcore.CfnGatewayTarget(\n this,\n \\`Target-\\${props.gatewayTargetName}\\`,\n {\n gatewayIdentifier: this.gateway.gatewayId,\n name: props.gatewayTargetName,\n targetConfiguration: {\n http: {\n agentcoreRuntime: {\n arn: props.agentRuntimeArn,\n qualifier: 'DEFAULT',\n },\n },\n },\n // The bare gateway IAM role credential: runtime targets reject the\n // iamCredentialProvider detail MCP targets carry.\n credentialProviderConfigurations: [\n {\n credentialProviderType: 'GATEWAY_IAM_ROLE',\n },\n ],\n },\n );\n\n // Grant the gateway role invoke access to the target runtime before the\n // target is created — AgentCore validates access to the runtime during\n // target creation.\n const grant = this.gateway.role.addToPrincipalPolicy(\n new iam.PolicyStatement({\n actions: [\n 'bedrock-agentcore:InvokeAgentRuntime',\n 'bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream',\n // A2A targets additionally serve their agent card via the gateway.\n 'bedrock-agentcore:GetAgentCard',\n ],\n resources: [props.agentRuntimeArn, \\`\\${props.agentRuntimeArn}/*\\`],\n }),\n );\n if (grant.policyDependable) {\n target.node.addDependency(grant.policyDependable);\n }\n\n return target;\n }`;\n\n/**\n * Add the `protocol` prop, its constructor handling and the agent-target\n * methods to the vended `AgentCoreGateway` core construct.\n */\nconst migrateGatewayConstruct = async (\n tree: Tree,\n nextSteps: string[],\n): Promise<void> => {\n if (!tree.exists(GATEWAY_CONSTRUCT_FILE)) {\n // No vended gateway construct in this workspace - nothing to migrate.\n return;\n }\n\n if (\n (tree.read(GATEWAY_CONSTRUCT_FILE, 'utf-8') ?? '').includes(\n 'addAgentTarget',\n )\n ) {\n // Already migrated.\n return;\n }\n\n const divergedMessage = `${GATEWAY_CONSTRUCT_FILE}: the AgentCoreGateway construct has diverged from the generated shape - left untouched. Re-run the agentcore-gateway generator in a fresh workspace to see the current construct, which supports agent runtime targets via a 'protocol' prop and addAgent()/addAgentTarget() methods.`;\n\n // Anchored on the shapes every vended version of the construct carries: the\n // props interface, the class field the protocol field is inserted after,\n // and the Gateway creation in the constructor.\n const hasVendedShape =\n (await matchGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n '`export interface AgentCoreGatewayProps { $_ }`',\n )) &&\n (await matchGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n '`private readonly targetRuntimeArns: string[] = []`',\n )) &&\n (await matchGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n \"`this.gateway = new agentcore.Gateway(this, 'Gateway', $_)`\",\n ));\n\n if (!hasVendedShape) {\n nextSteps.push(divergedMessage);\n return;\n }\n\n // 1. The protocol prop on AgentCoreGatewayProps. The placeholder keeps the\n // prop's doc comment (with its backticks) out of the GritQL pattern.\n await insertViaGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n `\\`export interface AgentCoreGatewayProps { $members }\\` where {\n $members <: not contains \\`protocol\\`\n} => \\`export interface AgentCoreGatewayProps { $members\n ${GRIT_INSERT_PLACEHOLDER}\n}\\``,\n PROTOCOL_PROP,\n );\n\n // 2. The protocol class field. Matched without the trailing semicolon —\n // GritQL parses the snippet standalone, where the semicolon is not part\n // of the field's AST node.\n await applyGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n `\\`private readonly targetRuntimeArns: string[] = []\\` as $field where {\n $program <: not contains \\`private readonly protocol\\`\n} => \\`$field;\n private readonly protocol: 'mcp' | 'http'\\``,\n );\n\n // 3. Assign the field and remove the protocol type for http gateways.\n await insertViaGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n `\\`this.gateway = new agentcore.Gateway($args);\\` as $stmt where {\n $program <: not contains \\`this.protocol = props\\`\n} => \\`${GRIT_INSERT_PLACEHOLDER}\n $stmt\\``,\n PROTOCOL_CONSTRUCTOR_STATEMENTS,\n );\n await insertViaGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n `\\`this.gateway = new agentcore.Gateway($args);\\` as $stmt where {\n $program <: not contains \\`addPropertyDeletionOverride\\`\n} => \\`$stmt\n${GRIT_INSERT_PLACEHOLDER}\\``,\n PROTOCOL_TYPE_REMOVAL,\n );\n\n // 4. The agent-target methods, inserted after addGatewayTarget (present in\n // every vended version that also has the readiness probe field).\n const addedMethods = await insertViaGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n `\\`public addGatewayTarget($params): agentcore.CfnGatewayTarget { $body }\\` as $method where {\n $program <: not contains \\`addAgentTarget\\`\n} => \\`$method\n${GRIT_INSERT_PLACEHOLDER}\\``,\n AGENT_TARGET_METHODS,\n );\n\n if (!addedMethods) {\n nextSteps.push(divergedMessage);\n return;\n }\n};\n\n/**\n * Add the `agentName` member to each vended agent construct, which\n * `AgentCoreGateway.addAgent` reads as the default gateway target name.\n */\nconst migrateAgentConstructs = async (\n tree: Tree,\n nextSteps: string[],\n): Promise<void> => {\n if (!tree.exists(AGENTS_DIR)) {\n return;\n }\n for (const dir of tree.children(AGENTS_DIR)) {\n const constructFile = `${AGENTS_DIR}/${dir}/${dir}.ts`;\n if (!tree.exists(constructFile)) {\n continue;\n }\n if ((tree.read(constructFile, 'utf-8') ?? '').includes('agentName')) {\n // Already migrated (or user-added).\n continue;\n }\n const added = await insertViaGritQL(\n tree,\n constructFile,\n `\\`public readonly agentCoreRuntime: Runtime\\` as $field => \\`$field;\n ${GRIT_INSERT_PLACEHOLDER}\\``,\n `/** Default Gateway target name for this agent. */\n public readonly agentName = '${dir}'`,\n );\n if (!added) {\n nextSteps.push(\n `${constructFile}: the agent construct has diverged from the generated shape - left untouched. To attach this agent to a gateway with addAgent(), add a \\`public readonly agentName = '${dir}';\\` member (or use addAgentTarget() with an explicit target name).`,\n );\n }\n }\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n await migrateGatewayConstruct(tree, nextSteps);\n await migrateAgentConstructs(tree, nextSteps);\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["applyGritQL","GRIT_INSERT_PLACEHOLDER","insertViaGritQL","matchGritQL","formatFilesInSubtree","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","GATEWAY_CONSTRUCT_FILE","AGENTS_DIR","PROTOCOL_PROP","PROTOCOL_CONSTRUCTOR_STATEMENTS","PROTOCOL_TYPE_REMOVAL","AGENT_TARGET_METHODS","migrateGatewayConstruct","tree","nextSteps","exists","read","includes","divergedMessage","hasVendedShape","push","addedMethods","migrateAgentConstructs","dir","children","constructFile","added","migration"],"mappings":"AAAA;;;CAGC,GAED,SACEA,WAAW,EACXC,uBAAuB,EACvBC,eAAe,EACfC,WAAW,QACN,wBAAqB;AAC5B,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SACEC,YAAY,EACZC,qBAAqB,QAChB,gDAA6C;AAEpD;;;;;;;;;;;;CAYC,GAED,MAAMC,yBAAyB,GAAGF,aAAa,CAAC,EAAEC,sBAAsB,gDAAgD,CAAC;AAEzH,MAAME,aAAa,GAAGH,aAAa,CAAC,EAAEC,sBAAsB,eAAe,CAAC;AAE5E,MAAMG,gBAAgB,CAAC;;;;;;;;;qCASc,CAAC;AAEtC,MAAMC,kCAAkC,CAAC;AACzC,CAAC;AAED,MAAMC,wBAAwB,CAAC;;;;;;;;KAQ1B,CAAC;AAEN,MAAMC,uBAAuB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsF3B,CAAC;AAEJ;;;CAGC,GACD,MAAMC,0BAA0B,OAC9BC,MACAC;IAEA,IAAI,CAACD,KAAKE,MAAM,CAACT,yBAAyB;QACxC,sEAAsE;QACtE;IACF;IAEA,IACE,AAACO,CAAAA,KAAKG,IAAI,CAACV,wBAAwB,YAAY,EAAC,EAAGW,QAAQ,CACzD,mBAEF;QACA,oBAAoB;QACpB;IACF;IAEA,MAAMC,kBAAkB,GAAGZ,uBAAuB,sRAAsR,CAAC;IAEzU,4EAA4E;IAC5E,yEAAyE;IACzE,+CAA+C;IAC/C,MAAMa,iBACJ,AAAC,MAAMjB,YACLW,MACAP,wBACA,sDAED,MAAMJ,YACLW,MACAP,wBACA,0DAED,MAAMJ,YACLW,MACAP,wBACA;IAGJ,IAAI,CAACa,gBAAgB;QACnBL,UAAUM,IAAI,CAACF;QACf;IACF;IAEA,2EAA2E;IAC3E,wEAAwE;IACxE,MAAMjB,gBACJY,MACAP,wBACA,CAAC;;;EAGH,EAAEN,wBAAwB;GACzB,CAAC,EACAQ;IAGF,wEAAwE;IACxE,2EAA2E;IAC3E,8BAA8B;IAC9B,MAAMT,YACJc,MACAP,wBACA,CAAC;;;6CAGwC,CAAC;IAG5C,sEAAsE;IACtE,MAAML,gBACJY,MACAP,wBACA,CAAC;;OAEE,EAAEN,wBAAwB;WACtB,CAAC,EACRS;IAEF,MAAMR,gBACJY,MACAP,wBACA,CAAC;;;AAGL,EAAEN,wBAAwB,EAAE,CAAC,EACzBU;IAGF,2EAA2E;IAC3E,oEAAoE;IACpE,MAAMW,eAAe,MAAMpB,gBACzBY,MACAP,wBACA,CAAC;;;AAGL,EAAEN,wBAAwB,EAAE,CAAC,EACzBW;IAGF,IAAI,CAACU,cAAc;QACjBP,UAAUM,IAAI,CAACF;QACf;IACF;AACF;AAEA;;;CAGC,GACD,MAAMI,yBAAyB,OAC7BT,MACAC;IAEA,IAAI,CAACD,KAAKE,MAAM,CAACR,aAAa;QAC5B;IACF;IACA,KAAK,MAAMgB,OAAOV,KAAKW,QAAQ,CAACjB,YAAa;QAC3C,MAAMkB,gBAAgB,GAAGlB,WAAW,CAAC,EAAEgB,IAAI,CAAC,EAAEA,IAAI,GAAG,CAAC;QACtD,IAAI,CAACV,KAAKE,MAAM,CAACU,gBAAgB;YAC/B;QACF;QACA,IAAI,AAACZ,CAAAA,KAAKG,IAAI,CAACS,eAAe,YAAY,EAAC,EAAGR,QAAQ,CAAC,cAAc;YAEnE;QACF;QACA,MAAMS,QAAQ,MAAMzB,gBAClBY,MACAY,eACA,CAAC;EACL,EAAEzB,wBAAwB,EAAE,CAAC,EACzB,CAAC;+BACwB,EAAEuB,IAAI,CAAC,CAAC;QAEnC,IAAI,CAACG,OAAO;YACVZ,UAAUM,IAAI,CACZ,GAAGK,cAAc,sKAAsK,EAAEF,IAAI,mEAAmE,CAAC;QAErQ;IACF;AACF;AAEA,eAAe,eAAeI,UAC5Bd,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,MAAMF,wBAAwBC,MAAMC;IACpC,MAAMQ,uBAAuBT,MAAMC;IAEnC,MAAMX,qBAAqBU;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { getProjects, joinPathFragments } from "@nx/devkit";
|
|
5
|
+
import { SMITHY_PROJECT_GENERATOR_INFO } from "../../../smithy/project/generator.js";
|
|
6
|
+
import { applyGritQL } from "../../../utils/ast.js";
|
|
7
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
8
|
+
import { isVendedUpgrade } from "../../../utils/version-upgrade-migration/vended-upgrade.js";
|
|
9
|
+
/**
|
|
10
|
+
* Hardcoded rather than read from `TS_VERSIONS`: this runs once, for the release
|
|
11
|
+
* that fixed the declaration naming, so it must keep applying that exact change
|
|
12
|
+
* however far the vended versions move afterwards. A workspace on a later release
|
|
13
|
+
* gets the newer pins from the version sync instead.
|
|
14
|
+
*/ const PINS = [
|
|
15
|
+
{
|
|
16
|
+
name: 'rolldown',
|
|
17
|
+
target: '1.2.0'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'rolldown-plugin-dts',
|
|
21
|
+
target: '0.28.0'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: '@rollup/plugin-esm-shim',
|
|
25
|
+
target: '0.1.8'
|
|
26
|
+
}
|
|
27
|
+
];
|
|
28
|
+
/** A version ends at whitespace, a line break or the end of the command. */ const VERSION = String.raw`[^\s\\]+`;
|
|
29
|
+
const escapeRegExp = (value)=>value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
30
|
+
/**
|
|
31
|
+
* Rewrite every occurrence of one pin to its target version.
|
|
32
|
+
*
|
|
33
|
+
* The pin is matched by name, so a `rolldown-plugin-dts@x` in the same command as
|
|
34
|
+
* `rolldown@y` keeps its own version — the `@` before the version terminates the
|
|
35
|
+
* match, so the shorter name does not match the longer one.
|
|
36
|
+
*/ const rewritePin = ({ name, target })=>`r"[\\s\\S]*${escapeRegExp(name)}@(${VERSION})[\\s\\S]*"($version) where { $version => \`${target}\` }`;
|
|
37
|
+
/** Whether the file pins this package behind the target version. */ const isBehindTarget = (contents, { name, target })=>{
|
|
38
|
+
const matches = contents.matchAll(new RegExp(`${escapeRegExp(name)}@(${VERSION})`, 'g'));
|
|
39
|
+
const declared = [
|
|
40
|
+
...matches
|
|
41
|
+
].flatMap((match)=>match[1] ? [
|
|
42
|
+
match[1]
|
|
43
|
+
] : []);
|
|
44
|
+
// A rewrite replaces every occurrence at once, so this has to hold for all of
|
|
45
|
+
// them. Compared rather than tested for inequality, so a workspace a later
|
|
46
|
+
// release has already moved past the target keeps its newer pin.
|
|
47
|
+
return declared.length > 0 && declared.every((version)=>isVendedUpgrade(target, version));
|
|
48
|
+
};
|
|
49
|
+
const divergedNextStep = (path)=>`${path}: the Smithy build image's bundle pins have diverged from the generated shape - left untouched. Update \`rolldown\` to 1.2.0 and \`rolldown-plugin-dts\` to 0.28.0.`;
|
|
50
|
+
export default async function migration(tree) {
|
|
51
|
+
const nextSteps = [];
|
|
52
|
+
// Only a Smithy service project bundles the SSDK; the shapes type builds the
|
|
53
|
+
// model alone and pins none of this.
|
|
54
|
+
const buildDockerfiles = [
|
|
55
|
+
...getProjects(tree).values()
|
|
56
|
+
].filter((project)=>{
|
|
57
|
+
const metadata = project.metadata;
|
|
58
|
+
return metadata?.generator === SMITHY_PROJECT_GENERATOR_INFO.id && metadata.smithyType === 'service';
|
|
59
|
+
}).map((project)=>joinPathFragments(project.root, 'build.Dockerfile')).filter((filePath)=>tree.exists(filePath));
|
|
60
|
+
for (const path of buildDockerfiles){
|
|
61
|
+
const contents = tree.read(path, 'utf-8') ?? '';
|
|
62
|
+
for (const pin of PINS){
|
|
63
|
+
if (!isBehindTarget(contents, pin)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (!await applyGritQL(tree, path, rewritePin(pin))) {
|
|
67
|
+
nextSteps.push(divergedNextStep(path));
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
await formatFilesInSubtree(tree);
|
|
73
|
+
return {
|
|
74
|
+
nextSteps
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/smithy-ssdk-bundle-pins/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n} from '@nx/devkit';\nimport { SMITHY_PROJECT_GENERATOR_INFO } from '../../../smithy/project/generator';\nimport { applyGritQL } from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { isVendedUpgrade } from '../../../utils/version-upgrade-migration/vended-upgrade';\n\n/**\n * Move a Smithy `build.Dockerfile` onto the SSDK bundle pins this release fixes.\n *\n * `rolldown-plugin-dts` named the bundled declaration after its content hash\n * before 0.20.0, so the generated handler's `./generated/ssdk/index.js` import\n * found no `index.d.ts` beside it and `compile` failed with TS7016. The two pins\n * move together: the plugin release that fixed the naming needs a rolldown past\n * the pin this shipped with.\n *\n * There is no Dockerfile grammar, so each pin is matched as an anchored rewrite\n * over the whole file with the version captured — `${...}` in these patterns is\n * GritQL metavariable syntax, not interpolation.\n */\n\n/** A pin in the file body, and the version this migration moves it to. */\ninterface Pin {\n /** The package as the install command names it. */\n readonly name: string;\n readonly target: string;\n}\n\n/**\n * Hardcoded rather than read from `TS_VERSIONS`: this runs once, for the release\n * that fixed the declaration naming, so it must keep applying that exact change\n * however far the vended versions move afterwards. A workspace on a later release\n * gets the newer pins from the version sync instead.\n */\nconst PINS: readonly Pin[] = [\n { name: 'rolldown', target: '1.2.0' },\n { name: 'rolldown-plugin-dts', target: '0.28.0' },\n { name: '@rollup/plugin-esm-shim', target: '0.1.8' },\n];\n\n/** A version ends at whitespace, a line break or the end of the command. */\nconst VERSION = String.raw`[^\\s\\\\]+`;\n\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * Rewrite every occurrence of one pin to its target version.\n *\n * The pin is matched by name, so a `rolldown-plugin-dts@x` in the same command as\n * `rolldown@y` keeps its own version — the `@` before the version terminates the\n * match, so the shorter name does not match the longer one.\n */\nconst rewritePin = ({ name, target }: Pin): string =>\n `r\"[\\\\s\\\\S]*${escapeRegExp(name)}@(${VERSION})[\\\\s\\\\S]*\"($version) where { $version => \\`${target}\\` }`;\n\n/** Whether the file pins this package behind the target version. */\nconst isBehindTarget = (contents: string, { name, target }: Pin): boolean => {\n const matches = contents.matchAll(\n new RegExp(`${escapeRegExp(name)}@(${VERSION})`, 'g'),\n );\n const declared = [...matches].flatMap((match) =>\n match[1] ? [match[1]] : [],\n );\n // A rewrite replaces every occurrence at once, so this has to hold for all of\n // them. Compared rather than tested for inequality, so a workspace a later\n // release has already moved past the target keeps its newer pin.\n return (\n declared.length > 0 &&\n declared.every((version) => isVendedUpgrade(target, version))\n );\n};\n\nconst divergedNextStep = (path: string): string =>\n `${path}: the Smithy build image's bundle pins have diverged from the generated shape - left untouched. Update \\`rolldown\\` to 1.2.0 and \\`rolldown-plugin-dts\\` to 0.28.0.`;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n // Only a Smithy service project bundles the SSDK; the shapes type builds the\n // model alone and pins none of this.\n const buildDockerfiles = [...getProjects(tree).values()]\n .filter((project) => {\n const metadata = project.metadata as\n | { generator?: string; smithyType?: string }\n | undefined;\n return (\n metadata?.generator === SMITHY_PROJECT_GENERATOR_INFO.id &&\n metadata.smithyType === 'service'\n );\n })\n .map((project) => joinPathFragments(project.root, 'build.Dockerfile'))\n .filter((filePath) => tree.exists(filePath));\n\n for (const path of buildDockerfiles) {\n const contents = tree.read(path, 'utf-8') ?? '';\n\n for (const pin of PINS) {\n if (!isBehindTarget(contents, pin)) {\n continue;\n }\n if (!(await applyGritQL(tree, path, rewritePin(pin)))) {\n nextSteps.push(divergedNextStep(path));\n break;\n }\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","joinPathFragments","SMITHY_PROJECT_GENERATOR_INFO","applyGritQL","formatFilesInSubtree","isVendedUpgrade","PINS","name","target","VERSION","String","raw","escapeRegExp","value","replace","rewritePin","isBehindTarget","contents","matches","matchAll","RegExp","declared","flatMap","match","length","every","version","divergedNextStep","path","migration","tree","nextSteps","buildDockerfiles","values","filter","project","metadata","generator","id","smithyType","map","root","filePath","exists","read","pin","push"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EACXC,iBAAiB,QAGZ,aAAa;AACpB,SAASC,6BAA6B,QAAQ,uCAAoC;AAClF,SAASC,WAAW,QAAQ,wBAAqB;AACjD,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SAASC,eAAe,QAAQ,6DAA0D;AAuB1F;;;;;CAKC,GACD,MAAMC,OAAuB;IAC3B;QAAEC,MAAM;QAAYC,QAAQ;IAAQ;IACpC;QAAED,MAAM;QAAuBC,QAAQ;IAAS;IAChD;QAAED,MAAM;QAA2BC,QAAQ;IAAQ;CACpD;AAED,0EAA0E,GAC1E,MAAMC,UAAUC,OAAOC,GAAG,CAAC,QAAQ,CAAC;AAEpC,MAAMC,eAAe,CAACC,QACpBA,MAAMC,OAAO,CAAC,uBAAuB;AAEvC;;;;;;CAMC,GACD,MAAMC,aAAa,CAAC,EAAER,IAAI,EAAEC,MAAM,EAAO,GACvC,CAAC,WAAW,EAAEI,aAAaL,MAAM,EAAE,EAAEE,QAAQ,4CAA4C,EAAED,OAAO,IAAI,CAAC;AAEzG,kEAAkE,GAClE,MAAMQ,iBAAiB,CAACC,UAAkB,EAAEV,IAAI,EAAEC,MAAM,EAAO;IAC7D,MAAMU,UAAUD,SAASE,QAAQ,CAC/B,IAAIC,OAAO,GAAGR,aAAaL,MAAM,EAAE,EAAEE,QAAQ,CAAC,CAAC,EAAE;IAEnD,MAAMY,WAAW;WAAIH;KAAQ,CAACI,OAAO,CAAC,CAACC,QACrCA,KAAK,CAAC,EAAE,GAAG;YAACA,KAAK,CAAC,EAAE;SAAC,GAAG,EAAE;IAE5B,8EAA8E;IAC9E,2EAA2E;IAC3E,iEAAiE;IACjE,OACEF,SAASG,MAAM,GAAG,KAClBH,SAASI,KAAK,CAAC,CAACC,UAAYrB,gBAAgBG,QAAQkB;AAExD;AAEA,MAAMC,mBAAmB,CAACC,OACxB,GAAGA,KAAK,mKAAmK,CAAC;AAE9K,eAAe,eAAeC,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,6EAA6E;IAC7E,qCAAqC;IACrC,MAAMC,mBAAmB;WAAIhC,YAAY8B,MAAMG,MAAM;KAAG,CACrDC,MAAM,CAAC,CAACC;QACP,MAAMC,WAAWD,QAAQC,QAAQ;QAGjC,OACEA,UAAUC,cAAcnC,8BAA8BoC,EAAE,IACxDF,SAASG,UAAU,KAAK;IAE5B,GACCC,GAAG,CAAC,CAACL,UAAYlC,kBAAkBkC,QAAQM,IAAI,EAAE,qBACjDP,MAAM,CAAC,CAACQ,WAAaZ,KAAKa,MAAM,CAACD;IAEpC,KAAK,MAAMd,QAAQI,iBAAkB;QACnC,MAAMf,WAAWa,KAAKc,IAAI,CAAChB,MAAM,YAAY;QAE7C,KAAK,MAAMiB,OAAOvC,KAAM;YACtB,IAAI,CAACU,eAAeC,UAAU4B,MAAM;gBAClC;YACF;YACA,IAAI,CAAE,MAAM1C,YAAY2B,MAAMF,MAAMb,WAAW8B,OAAQ;gBACrDd,UAAUe,IAAI,CAACnB,iBAAiBC;gBAChC;YACF;QACF;IACF;IAEA,MAAMxB,qBAAqB0B;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/v1.0.0-rc.50/modernize-function-props-cast/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type MigrationReturnObject,\n type Tree,\n visitNotIgnoredFiles,\n} from '@nx/devkit';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n} from '../../../utils/shared-constructs-constants';\n\n/**\n * Replace the legacy angle-bracket FunctionProps type assertion with the modern as syntax in generated API constructs\n *\n * The legacy `<FunctionProps>{ ... }` cast form is not supported by GritQL's\n * TypeScript parser, which silently breaks parsing (and therefore matching)\n * for the entire containing file. Since several other migrations rely on\n * GritQL to update these API construct files, this cast is replaced here with\n * the equivalent, GritQL-compatible `{ ... } as FunctionProps` form. This is\n * matched as an exact literal (rather than via GritQL) since GritQL cannot\n * parse the file while the legacy cast is still present.\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n *\n * Guardrails:\n * - Pattern-match before writing: skip files that have diverged from the shape\n * your generators produce and report them via `nextSteps`, or consider a\n * hybrid migration, rather than clobbering the user's changes.\n * - Idempotent: re-running must be a no-op.\n * - Format what you write: finish with `formatFilesInSubtree` so the files your\n * migration wrote are formatted correctly.\n */\n\nconst APIS_APP_DIR = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/app/apis`;\n\nconst OLD_CAST_OPEN = 'defaultIntegrationOptions: <FunctionProps>{';\nconst NEW_CAST_OPEN = 'defaultIntegrationOptions: {';\nconst OLD_CAST_CLOSE = '\\n },\\n buildDefaultIntegration:';\nconst NEW_CAST_CLOSE =\n '\\n } as FunctionProps,\\n buildDefaultIntegration:';\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n if (!tree.exists(APIS_APP_DIR)) {\n return { nextSteps };\n }\n\n const apiAppFiles: string[] = [];\n visitNotIgnoredFiles(tree, APIS_APP_DIR, (filePath) => {\n apiAppFiles.push(filePath);\n });\n\n for (const filePath of apiAppFiles) {\n if (!filePath.endsWith('.ts') || filePath.endsWith('/index.ts')) {\n continue;\n }\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes(OLD_CAST_OPEN)) {\n // Already migrated, or doesn't use this shape.\n continue;\n }\n if (!contents.includes(OLD_CAST_CLOSE)) {\n nextSteps.push(\n `${filePath}: the defaultIntegrationOptions cast has diverged from the generated shape - left untouched. Manually replace \\`<FunctionProps>{ ... }\\` with \\`{ ... } as FunctionProps\\`.`,\n );\n continue;\n }\n tree.write(\n filePath,\n contents\n .replace(OLD_CAST_OPEN, NEW_CAST_OPEN)\n .replace(OLD_CAST_CLOSE, NEW_CAST_CLOSE),\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["visitNotIgnoredFiles","formatFilesInSubtree","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","APIS_APP_DIR","OLD_CAST_OPEN","NEW_CAST_OPEN","OLD_CAST_CLOSE","NEW_CAST_CLOSE","migration","tree","nextSteps","exists","apiAppFiles","filePath","push","endsWith","contents","read","includes","write","replace"],"mappings":"AAAA;;;CAGC,GACD,SAGEA,oBAAoB,QACf,aAAa;AACpB,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SACEC,YAAY,EACZC,qBAAqB,QAChB,gDAA6C;AAEpD;;;;;;;;;;;;;;;;;;;;;;CAsBC,GAED,MAAMC,eAAe,GAAGF,aAAa,CAAC,EAAEC,sBAAsB,aAAa,CAAC;AAE5E,MAAME,gBAAgB;AACtB,MAAMC,gBAAgB;AACtB,MAAMC,iBAAiB;AACvB,MAAMC,iBACJ;AAEF,eAAe,eAAeC,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,IAAI,CAACD,KAAKE,MAAM,CAACR,eAAe;QAC9B,OAAO;YAAEO;QAAU;IACrB;IAEA,MAAME,cAAwB,EAAE;IAChCb,qBAAqBU,MAAMN,cAAc,CAACU;QACxCD,YAAYE,IAAI,CAACD;IACnB;IAEA,KAAK,MAAMA,YAAYD,YAAa;QAClC,IAAI,CAACC,SAASE,QAAQ,CAAC,UAAUF,SAASE,QAAQ,CAAC,cAAc;YAC/D;QACF;QACA,MAAMC,WAAWP,KAAKQ,IAAI,CAACJ,UAAU,YAAY;QACjD,IAAI,CAACG,SAASE,QAAQ,CAACd,gBAAgB;YAErC;QACF;QACA,IAAI,CAACY,SAASE,QAAQ,CAACZ,iBAAiB;YACtCI,UAAUI,IAAI,CACZ,GAAGD,SAAS,2KAA2K,CAAC;YAE1L;QACF;QACAJ,KAAKU,KAAK,CACRN,UACAG,SACGI,OAAO,CAAChB,eAAeC,eACvBe,OAAO,CAACd,gBAAgBC;IAE/B;IAEA,MAAMP,qBAAqBS;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/v1.0.0-rc.50/restrict-cors-to-custom-domains/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type MigrationReturnObject,\n type Tree,\n visitNotIgnoredFiles,\n} from '@nx/devkit';\nimport {\n addDestructuredImport,\n addStarExport,\n applyGritQL,\n} from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { isEsmWorkspace } from '../../../utils/module-format';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n} from '../../../utils/shared-constructs-constants';\n\n/**\n * Include CloudFront custom domain aliases in restrictCorsTo and UserIdentity callback URLs\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n *\n * Guardrails:\n * - Pattern-match before writing: skip files that have diverged from the shape\n * your generators produce and report them via `nextSteps`, rather than\n * clobbering the user's changes.\n * - Idempotent: re-running must be a no-op.\n * - Format what you write: finish with `formatFilesInSubtree` so the files your\n * migration wrote are formatted correctly.\n */\n\nconst CORE_DIR = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/core`;\nconst APIS_APP_DIR = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/app/apis`;\nconst CLOUDFRONT_CORE_FILE = `${CORE_DIR}/cloudfront.ts`;\nconst CORE_INDEX_FILE = `${CORE_DIR}/index.ts`;\nconst USER_IDENTITY_FILE = `${CORE_DIR}/user-identity.ts`;\n\nconst CLOUDFRONT_HELPER_CONTENT = `import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';\n\n/**\n * Finds the domain names associated with a CloudFront distribution.\n *\n * Includes the distribution's default \\`*.cloudfront.net\\` domain name plus any custom\n * domain names (aliases) configured on it.\n */\nexport const findCloudFrontDomainNames = (\n distribution: Distribution,\n): string[] => {\n const cfnDistribution = distribution.node.defaultChild as CfnDistribution;\n const distributionConfig =\n cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;\n return [distribution.domainName, ...(distributionConfig.aliases ?? [])];\n};\n`;\n\n// Rewrites the `restrictCorsTo` body as produced by generators prior to this fix.\nconst RESTRICT_CORS_TO_GRITQL_PATTERN =\n \"`origins.map(($o) => typeof $o === 'string' ? $o : 'cloudFrontDistribution' in $o ? $branch1 : $branch2)` where { $branch1 <: contains `distributionDomainName`, $branch2 <: contains `distributionDomainName` } => raw`origins.flatMap(($o) => typeof $o === 'string' ? [$o] : findCloudFrontDomainNames('cloudFrontDistribution' in $o ? $o.cloudFrontDistribution : $o).map((domain) => \\\\`https://${domain}\\\\`))`\";\n\n// Rewrites UserIdentity's callback/logout URL logic as produced by generators\n// prior to this fix.\nconst USER_IDENTITY_CALLBACK_URLS_GRITQL_PATTERN =\n '`this.findCloudFrontDomainNames()` => `Stack.of(this).node.findAll().filter((child): child is Distribution => child instanceof Distribution).flatMap(findCloudFrontDomainNames)`';\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n if (!tree.exists(CORE_INDEX_FILE)) {\n // No common/constructs shared library in this workspace - nothing to migrate.\n return { nextSteps };\n }\n\n const esm = isEsmWorkspace(tree);\n const apiCloudFrontImportSpecifier = esm\n ? '../../core/cloudfront.js'\n : '../../core/cloudfront';\n const coreCloudFrontImportSpecifier = esm\n ? './cloudfront.js'\n : './cloudfront';\n\n if (!tree.exists(CLOUDFRONT_CORE_FILE)) {\n tree.write(CLOUDFRONT_CORE_FILE, CLOUDFRONT_HELPER_CONTENT);\n }\n await addStarExport(tree, CORE_INDEX_FILE, './cloudfront.js');\n\n const apiAppFiles: string[] = [];\n visitNotIgnoredFiles(tree, APIS_APP_DIR, (filePath) => {\n apiAppFiles.push(filePath);\n });\n\n for (const filePath of apiAppFiles) {\n if (!filePath.endsWith('.ts') || filePath.endsWith('/index.ts')) {\n continue;\n }\n const rewrote = await applyGritQL(\n tree,\n filePath,\n RESTRICT_CORS_TO_GRITQL_PATTERN,\n );\n if (rewrote) {\n await addDestructuredImport(\n tree,\n filePath,\n ['findCloudFrontDomainNames'],\n apiCloudFrontImportSpecifier,\n );\n continue;\n }\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('findCloudFrontDomainNames(')) {\n nextSteps.push(\n `${filePath}: restrictCorsTo has diverged from the generated shape - left untouched. Manually apply the CloudFront custom domain fix (see findCloudFrontDomainNames in common/constructs/src/core/cloudfront.ts).`,\n );\n }\n // Otherwise already migrated - silent skip.\n }\n\n if (tree.exists(USER_IDENTITY_FILE)) {\n const rewrote = await applyGritQL(\n tree,\n USER_IDENTITY_FILE,\n USER_IDENTITY_CALLBACK_URLS_GRITQL_PATTERN,\n );\n if (rewrote) {\n await applyGritQL(\n tree,\n USER_IDENTITY_FILE,\n \"`import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront'` => `import { Distribution } from 'aws-cdk-lib/aws-cloudfront';`\",\n );\n await applyGritQL(\n tree,\n USER_IDENTITY_FILE,\n \"or { `// Includes each distribution's default domain name plus any custom domain names (aliases) configured on it.` => ., `private findCloudFrontDomainNames = (): string[] => $body` => . }\",\n );\n await addDestructuredImport(\n tree,\n USER_IDENTITY_FILE,\n ['findCloudFrontDomainNames'],\n coreCloudFrontImportSpecifier,\n );\n } else {\n const contents = tree.read(USER_IDENTITY_FILE, 'utf-8') ?? '';\n if (!contents.includes('.flatMap(findCloudFrontDomainNames)')) {\n nextSteps.push(\n `${USER_IDENTITY_FILE}: the callback URL logic has diverged from the generated shape - left untouched. Manually apply the shared findCloudFrontDomainNames helper (see common/constructs/src/core/cloudfront.ts).`,\n );\n }\n // Otherwise already migrated - silent skip.\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["visitNotIgnoredFiles","addDestructuredImport","addStarExport","applyGritQL","formatFilesInSubtree","isEsmWorkspace","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","CORE_DIR","APIS_APP_DIR","CLOUDFRONT_CORE_FILE","CORE_INDEX_FILE","USER_IDENTITY_FILE","CLOUDFRONT_HELPER_CONTENT","RESTRICT_CORS_TO_GRITQL_PATTERN","USER_IDENTITY_CALLBACK_URLS_GRITQL_PATTERN","migration","tree","nextSteps","exists","esm","apiCloudFrontImportSpecifier","coreCloudFrontImportSpecifier","write","apiAppFiles","filePath","push","endsWith","rewrote","contents","read","includes"],"mappings":"AAAA;;;CAGC,GACD,SAGEA,oBAAoB,QACf,aAAa;AACpB,SACEC,qBAAqB,EACrBC,aAAa,EACbC,WAAW,QACN,wBAAqB;AAC5B,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SAASC,cAAc,QAAQ,kCAA+B;AAC9D,SACEC,YAAY,EACZC,qBAAqB,QAChB,gDAA6C;AAEpD;;;;;;;;;;;;;;CAcC,GAED,MAAMC,WAAW,GAAGF,aAAa,CAAC,EAAEC,sBAAsB,SAAS,CAAC;AACpE,MAAME,eAAe,GAAGH,aAAa,CAAC,EAAEC,sBAAsB,aAAa,CAAC;AAC5E,MAAMG,uBAAuB,GAAGF,SAAS,cAAc,CAAC;AACxD,MAAMG,kBAAkB,GAAGH,SAAS,SAAS,CAAC;AAC9C,MAAMI,qBAAqB,GAAGJ,SAAS,iBAAiB,CAAC;AAEzD,MAAMK,4BAA4B,CAAC;;;;;;;;;;;;;;;;AAgBnC,CAAC;AAED,kFAAkF;AAClF,MAAMC,kCACJ;AAEF,8EAA8E;AAC9E,qBAAqB;AACrB,MAAMC,6CACJ;AAEF,eAAe,eAAeC,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,IAAI,CAACD,KAAKE,MAAM,CAACR,kBAAkB;QACjC,8EAA8E;QAC9E,OAAO;YAAEO;QAAU;IACrB;IAEA,MAAME,MAAMf,eAAeY;IAC3B,MAAMI,+BAA+BD,MACjC,6BACA;IACJ,MAAME,gCAAgCF,MAClC,oBACA;IAEJ,IAAI,CAACH,KAAKE,MAAM,CAACT,uBAAuB;QACtCO,KAAKM,KAAK,CAACb,sBAAsBG;IACnC;IACA,MAAMX,cAAce,MAAMN,iBAAiB;IAE3C,MAAMa,cAAwB,EAAE;IAChCxB,qBAAqBiB,MAAMR,cAAc,CAACgB;QACxCD,YAAYE,IAAI,CAACD;IACnB;IAEA,KAAK,MAAMA,YAAYD,YAAa;QAClC,IAAI,CAACC,SAASE,QAAQ,CAAC,UAAUF,SAASE,QAAQ,CAAC,cAAc;YAC/D;QACF;QACA,MAAMC,UAAU,MAAMzB,YACpBc,MACAQ,UACAX;QAEF,IAAIc,SAAS;YACX,MAAM3B,sBACJgB,MACAQ,UACA;gBAAC;aAA4B,EAC7BJ;YAEF;QACF;QACA,MAAMQ,WAAWZ,KAAKa,IAAI,CAACL,UAAU,YAAY;QACjD,IAAI,CAACI,SAASE,QAAQ,CAAC,+BAA+B;YACpDb,UAAUQ,IAAI,CACZ,GAAGD,SAAS,qMAAqM,CAAC;QAEtN;IACA,4CAA4C;IAC9C;IAEA,IAAIR,KAAKE,MAAM,CAACP,qBAAqB;QACnC,MAAMgB,UAAU,MAAMzB,YACpBc,MACAL,oBACAG;QAEF,IAAIa,SAAS;YACX,MAAMzB,YACJc,MACAL,oBACA;YAEF,MAAMT,YACJc,MACAL,oBACA;YAEF,MAAMX,sBACJgB,MACAL,oBACA;gBAAC;aAA4B,EAC7BU;QAEJ,OAAO;YACL,MAAMO,WAAWZ,KAAKa,IAAI,CAAClB,oBAAoB,YAAY;YAC3D,IAAI,CAACiB,SAASE,QAAQ,CAAC,wCAAwC;gBAC7Db,UAAUQ,IAAI,CACZ,GAAGd,mBAAmB,2LAA2L,CAAC;YAEtN;QACA,4CAA4C;QAC9C;IACF;IAEA,MAAMR,qBAAqBa;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
|