@aws/nx-plugin 1.0.0-rc.95 → 1.0.0-rc.97
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 +234 -38
- package/migrations.json +65 -2
- package/package.json +6 -6
- package/src/agentcore-gateway/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/agentcore-gateway/generator.js +6 -0
- package/src/agentcore-gateway/generator.js.map +1 -1
- package/src/agentcore-gateway/react-connection/__snapshots__/generator.spec.ts.snap +4 -1
- package/src/agentcore-harness/__snapshots__/generator.spec.ts.snap +68 -4
- package/src/agentcore-harness/generator.js +6 -0
- package/src/agentcore-harness/generator.js.map +1 -1
- package/src/connection/gateway-runtime-config.js +1 -1
- package/src/connection/gateway-runtime-config.js.map +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +10 -16
- package/src/infra/app/generator.js +34 -7
- package/src/infra/app/generator.js.map +1 -1
- package/src/init/generator.d.ts +1 -1
- package/src/init/generator.js +8 -6
- package/src/init/generator.js.map +1 -1
- package/src/init/schema.d.js.map +1 -1
- package/src/init/schema.d.ts +1 -0
- package/src/init/schema.json +5 -0
- package/src/mcp-server/server.js +2 -0
- package/src/mcp-server/server.js.map +1 -1
- package/src/mcp-server/tools/best-practices.d.ts +28 -0
- package/src/mcp-server/tools/best-practices.js +43 -0
- package/src/mcp-server/tools/best-practices.js.map +1 -0
- package/src/mcp-server/tools/general-guidance.d.ts +1 -1
- package/src/mcp-server/tools/general-guidance.js +13 -4
- package/src/mcp-server/tools/general-guidance.js.map +1 -1
- package/src/migrations/latest/checkov-scan-cache-inputs/metadata.json +3 -0
- package/src/migrations/latest/checkov-scan-cache-inputs/migration.d.ts +6 -0
- package/src/migrations/latest/checkov-scan-cache-inputs/migration.js +58 -0
- package/src/migrations/latest/checkov-scan-cache-inputs/migration.js.map +1 -0
- package/src/migrations/latest/gateway-url-accessor/__snapshots__/migration.spec.ts.snap +84 -0
- package/src/migrations/latest/gateway-url-accessor/metadata.json +3 -0
- package/src/migrations/latest/gateway-url-accessor/migration.d.ts +6 -0
- package/src/migrations/latest/gateway-url-accessor/migration.js +94 -0
- package/src/migrations/latest/gateway-url-accessor/migration.js.map +1 -0
- package/src/migrations/latest/infra-deploy-express-mode/metadata.json +1 -1
- package/src/migrations/latest/infra-deploy-express-mode/migration.js +26 -28
- package/src/migrations/latest/infra-deploy-express-mode/migration.js.map +1 -1
- package/src/migrations/latest/py-lambda-powertools-context/metadata.json +3 -0
- package/src/migrations/latest/py-lambda-powertools-context/migration.d.ts +6 -0
- package/src/migrations/latest/py-lambda-powertools-context/migration.js +58 -0
- package/src/migrations/latest/py-lambda-powertools-context/migration.js.map +1 -0
- package/src/migrations/latest/script-project-quality-gates/metadata.json +3 -0
- package/src/migrations/latest/script-project-quality-gates/migration.d.ts +6 -0
- package/src/migrations/latest/script-project-quality-gates/migration.js +53 -0
- package/src/migrations/latest/script-project-quality-gates/migration.js.map +1 -0
- package/src/migrations/latest/smithy-extension-trait-aliases/__snapshots__/migration.spec.ts.snap +25 -0
- package/src/migrations/latest/smithy-extension-trait-aliases/metadata.json +3 -0
- package/src/migrations/latest/smithy-extension-trait-aliases/migration.d.ts +28 -0
- package/src/migrations/latest/smithy-extension-trait-aliases/migration.js +75 -0
- package/src/migrations/latest/smithy-extension-trait-aliases/migration.js.map +1 -0
- package/src/migrations/latest/terraform-validate-without-backend/metadata.json +3 -0
- package/src/migrations/latest/terraform-validate-without-backend/migration.d.ts +6 -0
- package/src/migrations/latest/terraform-validate-without-backend/migration.js +84 -0
- package/src/migrations/latest/terraform-validate-without-backend/migration.js.map +1 -0
- package/src/preset/__snapshots__/generator.spec.ts.snap +3 -5
- package/src/preset/generator.js +4 -25
- package/src/preset/generator.js.map +1 -1
- 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/__snapshots__/generator.spec.ts.snap +4 -1
- package/src/py/agent/react-connection/generator.d.ts +29 -0
- package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +8 -10
- package/src/py/dynamodb/generator.js +34 -7
- package/src/py/dynamodb/generator.js.map +1 -1
- package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -1
- package/src/py/lambda-function/files/handler/__lambdaFunctionSnakeCase__.py.template +2 -1
- package/src/py/project/schema.json +3 -1
- package/src/py/rdb/__snapshots__/generator.spec.ts.snap +28 -12
- package/src/py/rdb/files/Dockerfile.create-db-user.template +7 -3
- package/src/py/rdb/files/Dockerfile.migration.template +7 -3
- package/src/py/rdb/generator.js +29 -28
- package/src/py/rdb/generator.js.map +1 -1
- package/src/smithy/react-connection/files/model/extensions.smithy.template +3 -3
- package/src/smithy/ts/api/generator.js +7 -2
- package/src/smithy/ts/api/generator.js.map +1 -1
- package/src/terraform/project/generator.js +34 -10
- package/src/terraform/project/generator.js.map +1 -1
- package/src/trpc/backend/generator.js +7 -1
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/react/generator.js +6 -0
- package/src/trpc/react/generator.js.map +1 -1
- package/src/ts/agent/generator.js +3 -3
- package/src/ts/agent/generator.js.map +1 -1
- package/src/ts/agent/react-connection/generator.d.ts +37 -0
- package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +2 -0
- package/src/ts/dynamodb/generator.js +30 -6
- package/src/ts/dynamodb/generator.js.map +1 -1
- package/src/ts/lib/biome.d.ts +15 -1
- package/src/ts/lib/biome.js +79 -63
- package/src/ts/lib/biome.js.map +1 -1
- package/src/ts/lib/generator.d.ts +13 -0
- package/src/ts/lib/generator.js +14 -9
- package/src/ts/lib/generator.js.map +1 -1
- package/src/ts/lib/ts-project-utils.d.ts +31 -1
- package/src/ts/lib/ts-project-utils.js +53 -0
- package/src/ts/lib/ts-project-utils.js.map +1 -1
- package/src/ts/lib/vitest.d.ts +6 -0
- package/src/ts/lib/vitest.js +16 -1
- package/src/ts/lib/vitest.js.map +1 -1
- package/src/ts/mcp-server/generator.js +3 -3
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +5 -0
- package/src/ts/rdb/files/Dockerfile.template +5 -0
- package/src/ts/rdb/generator.d.ts +8 -0
- package/src/ts/rdb/generator.js +28 -24
- package/src/ts/rdb/generator.js.map +1 -1
- package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +39 -0
- package/src/ts/rdb/trpc-connection/generator.js +13 -0
- package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
- package/src/ts/react-website/agui/files/common/src/components/__agentNameKebabCase__-chat.tsx.template +9 -0
- package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +4 -1
- package/src/ts/react-website/agui/generator.d.ts +21 -0
- package/src/ts/react-website/agui/generator.js +6 -2
- package/src/ts/react-website/agui/generator.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +26 -22
- package/src/ts/react-website/app/generator.d.ts +42 -0
- package/src/ts/react-website/app/generator.js +4 -8
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/utils/agent-connection/agent-connection.d.ts +2 -1
- package/src/utils/agent-connection/agent-connection.js +6 -1
- package/src/utils/agent-connection/agent-connection.js.map +1 -1
- package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +11 -7
- package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +14 -6
- package/src/utils/agent-core-packaging.js +5 -5
- package/src/utils/agent-core-packaging.js.map +1 -1
- package/src/utils/api-constructs/api-constructs.d.ts +5 -0
- package/src/utils/api-constructs/api-constructs.js +8 -0
- package/src/utils/api-constructs/api-constructs.js.map +1 -1
- package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +4 -2
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +4 -2
- package/src/utils/ast.d.ts +10 -0
- package/src/utils/ast.js +33 -0
- package/src/utils/ast.js.map +1 -1
- package/src/utils/dependencies.js +1 -10
- package/src/utils/dependencies.js.map +1 -1
- package/src/utils/docker.d.ts +11 -0
- package/src/utils/docker.js +16 -3
- package/src/utils/docker.js.map +1 -1
- package/src/utils/dynamodb-config.d.ts +48 -0
- package/src/utils/dynamodb-config.js +44 -0
- package/src/utils/dynamodb-config.js.map +1 -0
- package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +8 -4
- package/src/utils/git-secrets.d.ts +28 -0
- package/src/utils/git-secrets.js +66 -0
- package/src/utils/git-secrets.js.map +1 -0
- package/src/utils/init.js +7 -6
- package/src/utils/init.js.map +1 -1
- package/src/utils/local-project-dependency.d.ts +28 -0
- package/src/utils/local-project-dependency.js +40 -0
- package/src/utils/local-project-dependency.js.map +1 -0
- package/src/utils/nx.d.ts +14 -0
- package/src/utils/nx.js +30 -0
- package/src/utils/nx.js.map +1 -1
- package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +11 -6
- package/src/utils/script-project-targets.d.ts +26 -0
- package/src/utils/script-project-targets.js +75 -0
- package/src/utils/script-project-targets.js.map +1 -0
- package/src/utils/shared-shadcn.d.ts +13 -0
- package/src/utils/shared-shadcn.js +3 -2
- package/src/utils/shared-shadcn.js.map +1 -1
- package/src/utils/test.js +15 -0
- package/src/utils/test.js.map +1 -1
- package/src/utils/version-upgrade-migration/sync-vended-versions.js +4 -4
- package/src/utils/version-upgrade-migration/sync-vended-versions.js.map +1 -1
- package/src/utils/versions.d.ts +13 -9
- package/src/utils/versions.js +17 -8
- package/src/utils/versions.js.map +1 -1
- package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +8 -4
- package/src/py/dynamodb/files/__name__/__init__.py.template +0 -6
- package/src/py/dynamodb/files/__name__/entities/__init__.py.template +0 -4
- package/src/py/dynamodb/files/config.json.template +0 -24
- package/src/ts/dynamodb/files/config.json.template +0 -24
- package/src/ts/dynamodb/files/src/entities/index.ts.template +0 -1
- package/src/ts/dynamodb/files/src/index.ts.template +0 -2
package/src/mcp-server/server.js
CHANGED
|
@@ -7,6 +7,7 @@ import PackageJson from "../../package.json" with {
|
|
|
7
7
|
};
|
|
8
8
|
import { listGenerators } from "../utils/nx.js";
|
|
9
9
|
import { addToExistingProjectTool } from "./tools/add-to-existing-project.js";
|
|
10
|
+
import { addBestPracticesTool } from "./tools/best-practices.js";
|
|
10
11
|
import { addCreateWorkspaceCommandTool } from "./tools/create-workspace-command.js";
|
|
11
12
|
import { addGeneralGuidanceTool, TOOL_SELECTION_GUIDE } from "./tools/general-guidance.js";
|
|
12
13
|
import { addGeneratorGuideTool } from "./tools/generator-guide.js";
|
|
@@ -31,6 +32,7 @@ ${TOOL_SELECTION_GUIDE}
|
|
|
31
32
|
`
|
|
32
33
|
});
|
|
33
34
|
addGeneralGuidanceTool(server, generators);
|
|
35
|
+
addBestPracticesTool(server, generators);
|
|
34
36
|
addCreateWorkspaceCommandTool(server);
|
|
35
37
|
addListGeneratorsTool(server, generators);
|
|
36
38
|
addGeneratorGuideTool(server, generators);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/mcp-server/server.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport PackageJson from '../../package.json' with { type: 'json' };\nimport { listGenerators } from '../utils/nx.js';\nimport { addToExistingProjectTool } from './tools/add-to-existing-project.js';\nimport { addCreateWorkspaceCommandTool } from './tools/create-workspace-command.js';\nimport {\n addGeneralGuidanceTool,\n TOOL_SELECTION_GUIDE,\n} from './tools/general-guidance.js';\nimport { addGeneratorGuideTool } from './tools/generator-guide.js';\nimport { addListGeneratorsTool } from './tools/list-generators.js';\nimport { addUpgradeWorkspaceTool } from './tools/upgrade-workspace.js';\n\n/**\n * Create the MCP Server\n */\nexport const createServer = () => {\n const generators = listGenerators();\n\n const server = new McpServer(\n {\n name: 'nx-plugin-for-aws',\n version: PackageJson.version,\n },\n {\n instructions: `# Nx Plugin for AWS MCP Server\n\nThis server provides resources and tools for quickly scaffolding AWS projects within an Nx workspace (monorepo), using the Nx Plugin for AWS (@aws/nx-plugin).\n\nThe Nx Plugin for AWS provides \"generators\" to add projects or functionality to your workspace. Use this to build the foundations of any project you are building\non AWS, if the generators apply to your use case.\n\n${TOOL_SELECTION_GUIDE}\n`,\n },\n );\n\n addGeneralGuidanceTool(server, generators);\n addCreateWorkspaceCommandTool(server);\n addListGeneratorsTool(server, generators);\n addGeneratorGuideTool(server, generators);\n addToExistingProjectTool(server, generators);\n addUpgradeWorkspaceTool(server, generators);\n\n return server;\n};\n"],"names":["McpServer","PackageJson","type","listGenerators","addToExistingProjectTool","addCreateWorkspaceCommandTool","addGeneralGuidanceTool","TOOL_SELECTION_GUIDE","addGeneratorGuideTool","addListGeneratorsTool","addUpgradeWorkspaceTool","createServer","generators","server","name","version","instructions"],"mappings":"AAAA;;;CAGC,GACD,SAASA,SAAS,QAAQ,0CAA0C;AACpE,OAAOC,iBAAiB,0BAA0B;IAAEC,MAAM;AAAO,EAAE;AACnE,SAASC,cAAc,QAAQ,iBAAiB;AAChD,SAASC,wBAAwB,QAAQ,qCAAqC;AAC9E,SAASC,6BAA6B,QAAQ,sCAAsC;AACpF,SACEC,sBAAsB,EACtBC,oBAAoB,QACf,8BAA8B;AACrC,SAASC,qBAAqB,QAAQ,6BAA6B;AACnE,SAASC,qBAAqB,QAAQ,6BAA6B;AACnE,SAASC,uBAAuB,QAAQ,+BAA+B;AAEvE;;CAEC,GACD,OAAO,MAAMC,eAAe;IAC1B,MAAMC,
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/mcp-server/server.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport PackageJson from '../../package.json' with { type: 'json' };\nimport { listGenerators } from '../utils/nx.js';\nimport { addToExistingProjectTool } from './tools/add-to-existing-project.js';\nimport { addBestPracticesTool } from './tools/best-practices.js';\nimport { addCreateWorkspaceCommandTool } from './tools/create-workspace-command.js';\nimport {\n addGeneralGuidanceTool,\n TOOL_SELECTION_GUIDE,\n} from './tools/general-guidance.js';\nimport { addGeneratorGuideTool } from './tools/generator-guide.js';\nimport { addListGeneratorsTool } from './tools/list-generators.js';\nimport { addUpgradeWorkspaceTool } from './tools/upgrade-workspace.js';\n\n/**\n * Create the MCP Server\n */\nexport const createServer = () => {\n const generators = listGenerators();\n\n const server = new McpServer(\n {\n name: 'nx-plugin-for-aws',\n version: PackageJson.version,\n },\n {\n instructions: `# Nx Plugin for AWS MCP Server\n\nThis server provides resources and tools for quickly scaffolding AWS projects within an Nx workspace (monorepo), using the Nx Plugin for AWS (@aws/nx-plugin).\n\nThe Nx Plugin for AWS provides \"generators\" to add projects or functionality to your workspace. Use this to build the foundations of any project you are building\non AWS, if the generators apply to your use case.\n\n${TOOL_SELECTION_GUIDE}\n`,\n },\n );\n\n addGeneralGuidanceTool(server, generators);\n addBestPracticesTool(server, generators);\n addCreateWorkspaceCommandTool(server);\n addListGeneratorsTool(server, generators);\n addGeneratorGuideTool(server, generators);\n addToExistingProjectTool(server, generators);\n addUpgradeWorkspaceTool(server, generators);\n\n return server;\n};\n"],"names":["McpServer","PackageJson","type","listGenerators","addToExistingProjectTool","addBestPracticesTool","addCreateWorkspaceCommandTool","addGeneralGuidanceTool","TOOL_SELECTION_GUIDE","addGeneratorGuideTool","addListGeneratorsTool","addUpgradeWorkspaceTool","createServer","generators","server","name","version","instructions"],"mappings":"AAAA;;;CAGC,GACD,SAASA,SAAS,QAAQ,0CAA0C;AACpE,OAAOC,iBAAiB,0BAA0B;IAAEC,MAAM;AAAO,EAAE;AACnE,SAASC,cAAc,QAAQ,iBAAiB;AAChD,SAASC,wBAAwB,QAAQ,qCAAqC;AAC9E,SAASC,oBAAoB,QAAQ,4BAA4B;AACjE,SAASC,6BAA6B,QAAQ,sCAAsC;AACpF,SACEC,sBAAsB,EACtBC,oBAAoB,QACf,8BAA8B;AACrC,SAASC,qBAAqB,QAAQ,6BAA6B;AACnE,SAASC,qBAAqB,QAAQ,6BAA6B;AACnE,SAASC,uBAAuB,QAAQ,+BAA+B;AAEvE;;CAEC,GACD,OAAO,MAAMC,eAAe;IAC1B,MAAMC,aAAaV;IAEnB,MAAMW,SAAS,IAAId,UACjB;QACEe,MAAM;QACNC,SAASf,YAAYe,OAAO;IAC9B,GACA;QACEC,cAAc,CAAC;;;;;;;AAOrB,EAAET,qBAAqB;AACvB,CAAC;IACG;IAGFD,uBAAuBO,QAAQD;IAC/BR,qBAAqBS,QAAQD;IAC7BP,8BAA8BQ;IAC9BJ,sBAAsBI,QAAQD;IAC9BJ,sBAAsBK,QAAQD;IAC9BT,yBAAyBU,QAAQD;IACjCF,wBAAwBG,QAAQD;IAEhC,OAAOC;AACT,EAAE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
import type { NxGeneratorInfo } from '../../utils/generators.js';
|
|
7
|
+
/**
|
|
8
|
+
* Guide pages documenting behaviour that spans generators, so no single
|
|
9
|
+
* generator owns them and `generator-guide` never returns them. Each is
|
|
10
|
+
* described for the agent so it can pick the ones relevant to its task.
|
|
11
|
+
*/
|
|
12
|
+
export declare const BEST_PRACTICE_PAGES: {
|
|
13
|
+
readonly workspace: "Workspace layout, configuration and common commands";
|
|
14
|
+
readonly 'typescript-project': "Conventions for TypeScript projects";
|
|
15
|
+
readonly 'python-project': "Conventions for Python projects";
|
|
16
|
+
readonly security: "Security controls vended infrastructure carries, and the shared responsibility model";
|
|
17
|
+
readonly 'runtime-config': "How generated projects discover one another through AWS AppConfig";
|
|
18
|
+
readonly 'docker-bundling': "Building and deploying container images";
|
|
19
|
+
readonly 'local-development': "Running projects locally with the serve and dev targets";
|
|
20
|
+
};
|
|
21
|
+
export type BestPracticePage = keyof typeof BEST_PRACTICE_PAGES;
|
|
22
|
+
export declare const BEST_PRACTICE_PAGE_NAMES: BestPracticePage[];
|
|
23
|
+
/**
|
|
24
|
+
* Add a tool which serves the cross-cutting guide pages. Kept separate from
|
|
25
|
+
* `general-guidance` so an agent fetches only the pages its task needs rather
|
|
26
|
+
* than every page on every call.
|
|
27
|
+
*/
|
|
28
|
+
export declare const addBestPracticesTool: (server: McpServer, generators: NxGeneratorInfo[]) => void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { z } from "zod";
|
|
5
|
+
import { fetchGuidePages } from "../generator-info.js";
|
|
6
|
+
import { PackageManagerSchema } from "../schema.js";
|
|
7
|
+
/**
|
|
8
|
+
* Guide pages documenting behaviour that spans generators, so no single
|
|
9
|
+
* generator owns them and `generator-guide` never returns them. Each is
|
|
10
|
+
* described for the agent so it can pick the ones relevant to its task.
|
|
11
|
+
*/ export const BEST_PRACTICE_PAGES = {
|
|
12
|
+
workspace: 'Workspace layout, configuration and common commands',
|
|
13
|
+
'typescript-project': 'Conventions for TypeScript projects',
|
|
14
|
+
'python-project': 'Conventions for Python projects',
|
|
15
|
+
security: 'Security controls vended infrastructure carries, and the shared responsibility model',
|
|
16
|
+
'runtime-config': 'How generated projects discover one another through AWS AppConfig',
|
|
17
|
+
'docker-bundling': 'Building and deploying container images',
|
|
18
|
+
'local-development': 'Running projects locally with the serve and dev targets'
|
|
19
|
+
};
|
|
20
|
+
export const BEST_PRACTICE_PAGE_NAMES = Object.keys(BEST_PRACTICE_PAGES);
|
|
21
|
+
/**
|
|
22
|
+
* Add a tool which serves the cross-cutting guide pages. Kept separate from
|
|
23
|
+
* `general-guidance` so an agent fetches only the pages its task needs rather
|
|
24
|
+
* than every page on every call.
|
|
25
|
+
*/ export const addBestPracticesTool = (server, generators)=>{
|
|
26
|
+
server.registerTool('best-practices', {
|
|
27
|
+
title: 'Best Practices',
|
|
28
|
+
description: 'Tool to retrieve guidance which spans generators, rather than applying to one in particular. ' + 'Request the pages relevant to your task:\n' + Object.entries(BEST_PRACTICE_PAGES).map(([page, description])=>`- \`${page}\`: ${description}`).join('\n'),
|
|
29
|
+
inputSchema: {
|
|
30
|
+
packageManager: PackageManagerSchema.optional(),
|
|
31
|
+
pages: z.array(z.enum(BEST_PRACTICE_PAGE_NAMES)).min(1).describe('The guide pages to retrieve.')
|
|
32
|
+
}
|
|
33
|
+
}, async ({ packageManager, pages })=>({
|
|
34
|
+
content: [
|
|
35
|
+
{
|
|
36
|
+
type: 'text',
|
|
37
|
+
text: await fetchGuidePages(pages, generators, packageManager)
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}));
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=best-practices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/best-practices.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { NxGeneratorInfo } from '../../utils/generators.js';\nimport { fetchGuidePages } from '../generator-info.js';\nimport { PackageManagerSchema } from '../schema.js';\n\n/**\n * Guide pages documenting behaviour that spans generators, so no single\n * generator owns them and `generator-guide` never returns them. Each is\n * described for the agent so it can pick the ones relevant to its task.\n */\nexport const BEST_PRACTICE_PAGES = {\n workspace: 'Workspace layout, configuration and common commands',\n 'typescript-project': 'Conventions for TypeScript projects',\n 'python-project': 'Conventions for Python projects',\n security:\n 'Security controls vended infrastructure carries, and the shared responsibility model',\n 'runtime-config':\n 'How generated projects discover one another through AWS AppConfig',\n 'docker-bundling': 'Building and deploying container images',\n 'local-development':\n 'Running projects locally with the serve and dev targets',\n} as const satisfies Record<string, string>;\n\nexport type BestPracticePage = keyof typeof BEST_PRACTICE_PAGES;\n\nexport const BEST_PRACTICE_PAGE_NAMES = Object.keys(\n BEST_PRACTICE_PAGES,\n) as BestPracticePage[];\n\n/**\n * Add a tool which serves the cross-cutting guide pages. Kept separate from\n * `general-guidance` so an agent fetches only the pages its task needs rather\n * than every page on every call.\n */\nexport const addBestPracticesTool = (\n server: McpServer,\n generators: NxGeneratorInfo[],\n) => {\n server.registerTool(\n 'best-practices',\n {\n title: 'Best Practices',\n description:\n 'Tool to retrieve guidance which spans generators, rather than applying to one in particular. ' +\n 'Request the pages relevant to your task:\\n' +\n Object.entries(BEST_PRACTICE_PAGES)\n .map(([page, description]) => `- \\`${page}\\`: ${description}`)\n .join('\\n'),\n inputSchema: {\n packageManager: PackageManagerSchema.optional(),\n pages: z\n .array(z.enum(BEST_PRACTICE_PAGE_NAMES))\n .min(1)\n .describe('The guide pages to retrieve.'),\n },\n },\n async ({ packageManager, pages }) => ({\n content: [\n {\n type: 'text' as const,\n text: await fetchGuidePages(pages, generators, packageManager),\n },\n ],\n }),\n );\n};\n"],"names":["z","fetchGuidePages","PackageManagerSchema","BEST_PRACTICE_PAGES","workspace","security","BEST_PRACTICE_PAGE_NAMES","Object","keys","addBestPracticesTool","server","generators","registerTool","title","description","entries","map","page","join","inputSchema","packageManager","optional","pages","array","enum","min","describe","content","type","text"],"mappings":"AAAA;;;CAGC,GAED,SAASA,CAAC,QAAQ,MAAM;AAExB,SAASC,eAAe,QAAQ,uBAAuB;AACvD,SAASC,oBAAoB,QAAQ,eAAe;AAEpD;;;;CAIC,GACD,OAAO,MAAMC,sBAAsB;IACjCC,WAAW;IACX,sBAAsB;IACtB,kBAAkB;IAClBC,UACE;IACF,kBACE;IACF,mBAAmB;IACnB,qBACE;AACJ,EAA4C;AAI5C,OAAO,MAAMC,2BAA2BC,OAAOC,IAAI,CACjDL,qBACsB;AAExB;;;;CAIC,GACD,OAAO,MAAMM,uBAAuB,CAClCC,QACAC;IAEAD,OAAOE,YAAY,CACjB,kBACA;QACEC,OAAO;QACPC,aACE,kGACA,+CACAP,OAAOQ,OAAO,CAACZ,qBACZa,GAAG,CAAC,CAAC,CAACC,MAAMH,YAAY,GAAK,CAAC,IAAI,EAAEG,KAAK,IAAI,EAAEH,aAAa,EAC5DI,IAAI,CAAC;QACVC,aAAa;YACXC,gBAAgBlB,qBAAqBmB,QAAQ;YAC7CC,OAAOtB,EACJuB,KAAK,CAACvB,EAAEwB,IAAI,CAAClB,2BACbmB,GAAG,CAAC,GACJC,QAAQ,CAAC;QACd;IACF,GACA,OAAO,EAAEN,cAAc,EAAEE,KAAK,EAAE,GAAM,CAAA;YACpCK,SAAS;gBACP;oBACEC,MAAM;oBACNC,MAAM,MAAM5B,gBAAgBqB,OAAOX,YAAYS;gBACjD;aACD;QACH,CAAA;AAEJ,EAAE"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
6
|
import type { NxGeneratorInfo } from '../../utils/generators.js';
|
|
7
|
-
export declare const TOOL_SELECTION_GUIDE = "## Tool Selection Guide\n\n- Use the `general-guidance` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the `create-workspace-command` tool to discover how to create a workspace to start a new project.\n- Use the `add-to-existing-project` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.\n- Use the `upgrade-workspace` tool when upgrading Nx or the Nx Plugin for AWS to a newer version.\n- Use the `list-generators` tool to discover the available generators and how to run them.\n- Use the `generator-guide` tool to retrieve detailed information about a specific generator.";
|
|
7
|
+
export declare const TOOL_SELECTION_GUIDE = "## Tool Selection Guide\n\n- Use the `general-guidance` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the `best-practices` tool for guidance which spans generators rather than applying to one in particular, such as workspace layout, security, runtime configuration, container builds and local development.\n- Use the `create-workspace-command` tool to discover how to create a workspace to start a new project.\n- Use the `add-to-existing-project` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.\n- Use the `upgrade-workspace` tool when upgrading Nx or the Nx Plugin for AWS to a newer version.\n- Use the `list-generators` tool to discover the available generators and how to run them.\n- Use the `generator-guide` tool to retrieve detailed information about a specific generator.";
|
|
8
8
|
/**
|
|
9
9
|
* Add a tool which provides general guidance for using Nx and the Nx Plugin for AWS
|
|
10
10
|
*/
|
|
@@ -4,9 +4,20 @@
|
|
|
4
4
|
*/ import { IAC_PROVIDERS } from "../../utils/iac-providers.js";
|
|
5
5
|
import { buildNxCommand, fetchGuidePages } from "../generator-info.js";
|
|
6
6
|
import { PACKAGE_MANAGERS } from "../schema.js";
|
|
7
|
+
import { BEST_PRACTICE_PAGE_NAMES } from "./best-practices.js";
|
|
8
|
+
/**
|
|
9
|
+
* The cross-cutting pages every agent needs regardless of task, inlined here
|
|
10
|
+
* so a workspace's conventions land without a second tool call. The rest are
|
|
11
|
+
* served on demand by `best-practices`.
|
|
12
|
+
*/ const GENERAL_GUIDANCE_PAGES = [
|
|
13
|
+
'workspace',
|
|
14
|
+
'typescript-project',
|
|
15
|
+
'python-project'
|
|
16
|
+
];
|
|
7
17
|
export const TOOL_SELECTION_GUIDE = `## Tool Selection Guide
|
|
8
18
|
|
|
9
19
|
- Use the \`general-guidance\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.
|
|
20
|
+
- Use the \`best-practices\` tool for guidance which spans generators rather than applying to one in particular, such as workspace layout, security, runtime configuration, container builds and local development.
|
|
10
21
|
- Use the \`create-workspace-command\` tool to discover how to create a workspace to start a new project.
|
|
11
22
|
- Use the \`add-to-existing-project\` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.
|
|
12
23
|
- Use the \`upgrade-workspace\` tool when upgrading Nx or the Nx Plugin for AWS to a newer version.
|
|
@@ -86,12 +97,10 @@ ${PACKAGE_MANAGERS.map((pm)=>` \`\`\`bash
|
|
|
86
97
|
|
|
87
98
|
## Detailed Guides
|
|
88
99
|
|
|
89
|
-
Please refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects.
|
|
100
|
+
Please refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects. Use the \`best-practices\` tool for the remaining cross-cutting guides (${BEST_PRACTICE_PAGE_NAMES.filter((p)=>!GENERAL_GUIDANCE_PAGES.includes(p)).map((p)=>`\`${p}\``).join(', ')}).
|
|
90
101
|
|
|
91
102
|
${await fetchGuidePages([
|
|
92
|
-
|
|
93
|
-
'typescript-project',
|
|
94
|
-
'python-project'
|
|
103
|
+
...GENERAL_GUIDANCE_PAGES
|
|
95
104
|
], generators)}
|
|
96
105
|
|
|
97
106
|
`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/general-guidance.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { NxGeneratorInfo } from '../../utils/generators.js';\nimport { IAC_PROVIDERS } from '../../utils/iac-providers.js';\nimport { buildNxCommand, fetchGuidePages } from '../generator-info.js';\nimport { PACKAGE_MANAGERS } from '../schema.js';\n\nexport const TOOL_SELECTION_GUIDE = `## Tool Selection Guide\n\n- Use the \\`general-guidance\\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the \\`create-workspace-command\\` tool to discover how to create a workspace to start a new project.\n- Use the \\`add-to-existing-project\\` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.\n- Use the \\`upgrade-workspace\\` tool when upgrading Nx or the Nx Plugin for AWS to a newer version.\n- Use the \\`list-generators\\` tool to discover the available generators and how to run them.\n- Use the \\`generator-guide\\` tool to retrieve detailed information about a specific generator.`;\n\n/**\n * Add a tool which provides general guidance for using Nx and the Nx Plugin for AWS\n */\nexport const addGeneralGuidanceTool = (\n server: McpServer,\n generators: NxGeneratorInfo[],\n) => {\n server.registerTool(\n 'general-guidance',\n {\n title: 'General Guidance',\n description:\n 'Tool for guidance and best practices for working with Nx and the Nx Plugin for AWS',\n },\n async () => ({\n content: [\n {\n type: 'text' as const,\n text: `# Nx Plugin for AWS Guidance\n\n${TOOL_SELECTION_GUIDE}\n\n## Getting Started\n\n- Choose a package manager first. You can choose between ${PACKAGE_MANAGERS.join(', ')}. It's recommended to use \"pnpm\" if the user has no preference\n- Choose an infrastructure as code (IaC) provider next. You can choose between ${IAC_PROVIDERS.join(', ')}. It's recommended to use CDK if the user has no preference\n- Next, you must create an Nx workspace. Use the \\`create-workspace-command\\` tool for more details, and provide it with your chosen package manager\n- After this, you can start scaffolding the main components of your application using generators. Use the \\`list-generators\\` tool to discover available generators, and the \\`generator-guide\\` tool for more detailed information about a specific generator\n\n## Nx Primer\n\n- Prefix nx commands with the appropriate prefix for your package manager, for example:\n${PACKAGE_MANAGERS.map((pm) => buildNxCommand('<options>', pm)).join(' - \\n')}\n- Each project in your workspace has a file named \\`project.json\\` which contains important project information such as its name, and defines the \"targets\" which can be run for that project, for example building or testing the project\n- Use the command \\`nx reset\\` to reset the Nx daemon when unexpected issues arise\n- After adding dependencies between TypeScript projects, use \\`nx sync\\` to ensure project references are set up correctly\n\n## General Instructions\n\n- Each project declares the third-party runtime dependencies its source imports in its own \\`package.json\\`; shared build/test tooling (test runners, bundlers, etc.) is declared in the root \\`package.json\\` \\`devDependencies\\`. Versions follow a single version policy, recorded in the package manager's dependency catalog where supported (referenced as \\`catalog:\\`). Install with the appropriate command for your package manager:\n - Add a project runtime dependency: \\`pnpm add <package> --filter <project>\\` / \\`yarn workspace <project> add <package>\\` / \\`npm install <package> -w <project>\\` / \\`bun add <package> --cwd <project-directory>\\`\n - Add a shared dev tool at the root: \\`pnpm add -Dw <package>\\` / \\`yarn add -D <package>\\` / \\`npm install --legacy-peer-deps -D <package>\\` / \\`bun install -D <package>\\`\n- The \\`noUndeclaredDependencies\\` lint rule enforces that a project's source only imports packages declared in its own \\`package.json\\`\n- Projects in the same workspace can import one another directly by package name (eg \\`@workspace-name/project-name\\`) without declaring a dependency in \\`package.json\\` — TypeScript path aliases in \\`tsconfig.base.json\\` resolve these imports\n- When specifying project names as arguments to generators, prefer the _fully qualified_ project name, for example \\`@workspace-name/project-name\\`. Check the \\`project.json\\` file for the specific package to find its fully qualified name\n- When no generator exists for a specific framework required, use the base \\`ts#project\\` and \\`py#project\\` generators and build on top.\n- Leave the \\`--infra\\` option at its default value unless the user has explicitly instructed otherwise. Generators choose a sensible default type of infrastructure to deploy the project with, so only override \\`--infra\\` when the user has specified a particular requirement.\n\n## Useful Commands\n\n- Fix lint issues with \\`nx run-many --target lint --configuration=fix --all --output-style=stream\\`\n- Build all projects with \\`nx run-many --target build --all --output-style=stream\\`\n- Prefer importing the CDK constructs vended by generators in \\`packages/common/constructs\\` over writing your own\n\n## Best Practices\n\n- After running a generator, use the \\`nx show projects\\` command to check which projects have been added (if any)\n- Carefully examine the files that have been generated and always refer back to the generator guide when working in a generated project\n- Generate all projects into the \\`packages/\\` directory\n- After making changes to your projects, fix linting issues, then run a full build\n- When it's time to start testing a project, suggest to the user that infrastructure is deployed to AWS. For websites, if a runtime-config.json is needed, use the load-runtime-config target after a deployment to point a local website at a sandbox stack.\n- For CDK infrastructure projects, deploy the sandbox stage with the \\`deploy-sandbox\\` target (eg \\`nx deploy-sandbox infra\\`) rather than passing a stage pattern to \\`deploy\\` — it already targets the sandbox stage declared in \\`main.ts\\`. Likewise \\`destroy-sandbox\\` tears that stage back down.\n\n## Batching Generators\n\nWhen scaffolding several projects in one go, chain generators to avoid a slow dependency install after every generator:\n\n- **Chain generators** with \\`&&\\` in a single command. Pass \\`--prefer-install-dependencies=false\\` on each generator except the last so dependencies install once at the end, for example:\n\n${PACKAGE_MANAGERS.map(\n (pm) => ` \\`\\`\\`bash\n ${buildNxCommand('g @aws/nx-plugin:ts#trpc-api --no-interactive --name=my-app-api --auth=iam --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#react-website --no-interactive --name=my-app-website --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:connection --no-interactive --sourceProject=@my-app/my-app-website --targetProject=@my-app/my-app-api --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#infra --no-interactive --name=infra', pm)} && \\\\\n ${buildNxCommand('sync', pm)}\n \\`\\`\\``,\n).join('\\n')}\n\n- **\\`--prefer-install-dependencies=false\\`** asks a generator to defer its dependency install so the batch installs once at the end (the final generator above omits the flag and installs everything).\n- **\\`nx sync\\`** is required before building — generators modify TypeScript project references.\n\n## Detailed Guides\n\nPlease refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects.\n\n${await fetchGuidePages(['workspace', 'typescript-project', 'python-project'], generators)}\n\n `,\n },\n ],\n }),\n );\n};\n"],"names":["IAC_PROVIDERS","buildNxCommand","fetchGuidePages","PACKAGE_MANAGERS","TOOL_SELECTION_GUIDE","addGeneralGuidanceTool","server","generators","registerTool","title","description","content","type","text","join","map","pm"],"mappings":"AAAA;;;CAGC,GAGD,SAASA,aAAa,QAAQ,+BAA+B;AAC7D,SAASC,cAAc,EAAEC,eAAe,QAAQ,uBAAuB;AACvE,SAASC,gBAAgB,QAAQ,eAAe;AAEhD,OAAO,MAAMC,uBAAuB,CAAC;;;;;;;+FAO0D,CAAC,CAAC;AAEjG;;CAEC,GACD,OAAO,MAAMC,yBAAyB,CACpCC,QACAC;IAEAD,OAAOE,YAAY,CACjB,oBACA;QACEC,OAAO;QACPC,aACE;IACJ,GACA,UAAa,CAAA;YACXC,SAAS;gBACP;oBACEC,MAAM;oBACNC,MAAM,CAAC;;AAEjB,EAAET,qBAAqB;;;;yDAIkC,EAAED,iBAAiBW,IAAI,CAAC,MAAM;+EACR,EAAEd,cAAcc,IAAI,CAAC,MAAM;;;;;;;AAO1G,EAAEX,iBAAiBY,GAAG,CAAC,CAACC,KAAOf,eAAe,aAAae,KAAKF,IAAI,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqC9E,EAAEX,iBAAiBY,GAAG,CACpB,CAACC,KAAO,CAAC;EACT,EAAEf,eAAe,kHAAkHe,IAAI;IACrI,EAAEf,eAAe,gHAAgHe,IAAI;IACrI,EAAEf,eAAe,8JAA8Je,IAAI;IACnL,EAAEf,eAAe,2DAA2De,IAAI;IAChF,EAAEf,eAAe,QAAQe,IAAI;QACzB,CAAC,EACPF,IAAI,CAAC,MAAM;;;;;;;;;AASb,EAAE,MAAMZ,gBAAgB;wBAAC;wBAAa;wBAAsB;qBAAiB,EAAEK,YAAY;;IAEvF,CAAC;gBACG;aACD;QACH,CAAA;AAEJ,EAAE"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/general-guidance.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { NxGeneratorInfo } from '../../utils/generators.js';\nimport { IAC_PROVIDERS } from '../../utils/iac-providers.js';\nimport { buildNxCommand, fetchGuidePages } from '../generator-info.js';\nimport { PACKAGE_MANAGERS } from '../schema.js';\nimport { BEST_PRACTICE_PAGE_NAMES } from './best-practices.js';\n\n/**\n * The cross-cutting pages every agent needs regardless of task, inlined here\n * so a workspace's conventions land without a second tool call. The rest are\n * served on demand by `best-practices`.\n */\nconst GENERAL_GUIDANCE_PAGES = [\n 'workspace',\n 'typescript-project',\n 'python-project',\n] as const;\n\nexport const TOOL_SELECTION_GUIDE = `## Tool Selection Guide\n\n- Use the \\`general-guidance\\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the \\`best-practices\\` tool for guidance which spans generators rather than applying to one in particular, such as workspace layout, security, runtime configuration, container builds and local development.\n- Use the \\`create-workspace-command\\` tool to discover how to create a workspace to start a new project.\n- Use the \\`add-to-existing-project\\` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.\n- Use the \\`upgrade-workspace\\` tool when upgrading Nx or the Nx Plugin for AWS to a newer version.\n- Use the \\`list-generators\\` tool to discover the available generators and how to run them.\n- Use the \\`generator-guide\\` tool to retrieve detailed information about a specific generator.`;\n\n/**\n * Add a tool which provides general guidance for using Nx and the Nx Plugin for AWS\n */\nexport const addGeneralGuidanceTool = (\n server: McpServer,\n generators: NxGeneratorInfo[],\n) => {\n server.registerTool(\n 'general-guidance',\n {\n title: 'General Guidance',\n description:\n 'Tool for guidance and best practices for working with Nx and the Nx Plugin for AWS',\n },\n async () => ({\n content: [\n {\n type: 'text' as const,\n text: `# Nx Plugin for AWS Guidance\n\n${TOOL_SELECTION_GUIDE}\n\n## Getting Started\n\n- Choose a package manager first. You can choose between ${PACKAGE_MANAGERS.join(', ')}. It's recommended to use \"pnpm\" if the user has no preference\n- Choose an infrastructure as code (IaC) provider next. You can choose between ${IAC_PROVIDERS.join(', ')}. It's recommended to use CDK if the user has no preference\n- Next, you must create an Nx workspace. Use the \\`create-workspace-command\\` tool for more details, and provide it with your chosen package manager\n- After this, you can start scaffolding the main components of your application using generators. Use the \\`list-generators\\` tool to discover available generators, and the \\`generator-guide\\` tool for more detailed information about a specific generator\n\n## Nx Primer\n\n- Prefix nx commands with the appropriate prefix for your package manager, for example:\n${PACKAGE_MANAGERS.map((pm) => buildNxCommand('<options>', pm)).join(' - \\n')}\n- Each project in your workspace has a file named \\`project.json\\` which contains important project information such as its name, and defines the \"targets\" which can be run for that project, for example building or testing the project\n- Use the command \\`nx reset\\` to reset the Nx daemon when unexpected issues arise\n- After adding dependencies between TypeScript projects, use \\`nx sync\\` to ensure project references are set up correctly\n\n## General Instructions\n\n- Each project declares the third-party runtime dependencies its source imports in its own \\`package.json\\`; shared build/test tooling (test runners, bundlers, etc.) is declared in the root \\`package.json\\` \\`devDependencies\\`. Versions follow a single version policy, recorded in the package manager's dependency catalog where supported (referenced as \\`catalog:\\`). Install with the appropriate command for your package manager:\n - Add a project runtime dependency: \\`pnpm add <package> --filter <project>\\` / \\`yarn workspace <project> add <package>\\` / \\`npm install <package> -w <project>\\` / \\`bun add <package> --cwd <project-directory>\\`\n - Add a shared dev tool at the root: \\`pnpm add -Dw <package>\\` / \\`yarn add -D <package>\\` / \\`npm install --legacy-peer-deps -D <package>\\` / \\`bun install -D <package>\\`\n- The \\`noUndeclaredDependencies\\` lint rule enforces that a project's source only imports packages declared in its own \\`package.json\\`\n- Projects in the same workspace can import one another directly by package name (eg \\`@workspace-name/project-name\\`) without declaring a dependency in \\`package.json\\` — TypeScript path aliases in \\`tsconfig.base.json\\` resolve these imports\n- When specifying project names as arguments to generators, prefer the _fully qualified_ project name, for example \\`@workspace-name/project-name\\`. Check the \\`project.json\\` file for the specific package to find its fully qualified name\n- When no generator exists for a specific framework required, use the base \\`ts#project\\` and \\`py#project\\` generators and build on top.\n- Leave the \\`--infra\\` option at its default value unless the user has explicitly instructed otherwise. Generators choose a sensible default type of infrastructure to deploy the project with, so only override \\`--infra\\` when the user has specified a particular requirement.\n\n## Useful Commands\n\n- Fix lint issues with \\`nx run-many --target lint --configuration=fix --all --output-style=stream\\`\n- Build all projects with \\`nx run-many --target build --all --output-style=stream\\`\n- Prefer importing the CDK constructs vended by generators in \\`packages/common/constructs\\` over writing your own\n\n## Best Practices\n\n- After running a generator, use the \\`nx show projects\\` command to check which projects have been added (if any)\n- Carefully examine the files that have been generated and always refer back to the generator guide when working in a generated project\n- Generate all projects into the \\`packages/\\` directory\n- After making changes to your projects, fix linting issues, then run a full build\n- When it's time to start testing a project, suggest to the user that infrastructure is deployed to AWS. For websites, if a runtime-config.json is needed, use the load-runtime-config target after a deployment to point a local website at a sandbox stack.\n- For CDK infrastructure projects, deploy the sandbox stage with the \\`deploy-sandbox\\` target (eg \\`nx deploy-sandbox infra\\`) rather than passing a stage pattern to \\`deploy\\` — it already targets the sandbox stage declared in \\`main.ts\\`. Likewise \\`destroy-sandbox\\` tears that stage back down.\n\n## Batching Generators\n\nWhen scaffolding several projects in one go, chain generators to avoid a slow dependency install after every generator:\n\n- **Chain generators** with \\`&&\\` in a single command. Pass \\`--prefer-install-dependencies=false\\` on each generator except the last so dependencies install once at the end, for example:\n\n${PACKAGE_MANAGERS.map(\n (pm) => ` \\`\\`\\`bash\n ${buildNxCommand('g @aws/nx-plugin:ts#trpc-api --no-interactive --name=my-app-api --auth=iam --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#react-website --no-interactive --name=my-app-website --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:connection --no-interactive --sourceProject=@my-app/my-app-website --targetProject=@my-app/my-app-api --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#infra --no-interactive --name=infra', pm)} && \\\\\n ${buildNxCommand('sync', pm)}\n \\`\\`\\``,\n).join('\\n')}\n\n- **\\`--prefer-install-dependencies=false\\`** asks a generator to defer its dependency install so the batch installs once at the end (the final generator above omits the flag and installs everything).\n- **\\`nx sync\\`** is required before building — generators modify TypeScript project references.\n\n## Detailed Guides\n\nPlease refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects. Use the \\`best-practices\\` tool for the remaining cross-cutting guides (${BEST_PRACTICE_PAGE_NAMES.filter(\n (p) => !GENERAL_GUIDANCE_PAGES.includes(p as never),\n )\n .map((p) => `\\`${p}\\``)\n .join(', ')}).\n\n${await fetchGuidePages([...GENERAL_GUIDANCE_PAGES], generators)}\n\n `,\n },\n ],\n }),\n );\n};\n"],"names":["IAC_PROVIDERS","buildNxCommand","fetchGuidePages","PACKAGE_MANAGERS","BEST_PRACTICE_PAGE_NAMES","GENERAL_GUIDANCE_PAGES","TOOL_SELECTION_GUIDE","addGeneralGuidanceTool","server","generators","registerTool","title","description","content","type","text","join","map","pm","filter","p","includes"],"mappings":"AAAA;;;CAGC,GAGD,SAASA,aAAa,QAAQ,+BAA+B;AAC7D,SAASC,cAAc,EAAEC,eAAe,QAAQ,uBAAuB;AACvE,SAASC,gBAAgB,QAAQ,eAAe;AAChD,SAASC,wBAAwB,QAAQ,sBAAsB;AAE/D;;;;CAIC,GACD,MAAMC,yBAAyB;IAC7B;IACA;IACA;CACD;AAED,OAAO,MAAMC,uBAAuB,CAAC;;;;;;;;+FAQ0D,CAAC,CAAC;AAEjG;;CAEC,GACD,OAAO,MAAMC,yBAAyB,CACpCC,QACAC;IAEAD,OAAOE,YAAY,CACjB,oBACA;QACEC,OAAO;QACPC,aACE;IACJ,GACA,UAAa,CAAA;YACXC,SAAS;gBACP;oBACEC,MAAM;oBACNC,MAAM,CAAC;;AAEjB,EAAET,qBAAqB;;;;yDAIkC,EAAEH,iBAAiBa,IAAI,CAAC,MAAM;+EACR,EAAEhB,cAAcgB,IAAI,CAAC,MAAM;;;;;;;AAO1G,EAAEb,iBAAiBc,GAAG,CAAC,CAACC,KAAOjB,eAAe,aAAaiB,KAAKF,IAAI,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqC9E,EAAEb,iBAAiBc,GAAG,CACpB,CAACC,KAAO,CAAC;EACT,EAAEjB,eAAe,kHAAkHiB,IAAI;IACrI,EAAEjB,eAAe,gHAAgHiB,IAAI;IACrI,EAAEjB,eAAe,8JAA8JiB,IAAI;IACnL,EAAEjB,eAAe,2DAA2DiB,IAAI;IAChF,EAAEjB,eAAe,QAAQiB,IAAI;QACzB,CAAC,EACPF,IAAI,CAAC,MAAM;;;;;;;2MAO8L,EAAEZ,yBAAyBe,MAAM,CAChO,CAACC,IAAM,CAACf,uBAAuBgB,QAAQ,CAACD,IAEvCH,GAAG,CAAC,CAACG,IAAM,CAAC,EAAE,EAAEA,EAAE,EAAE,CAAC,EACrBJ,IAAI,CAAC,MAAM;;AAExB,EAAE,MAAMd,gBAAgB;2BAAIG;qBAAuB,EAAEI,YAAY;;IAE7D,CAAC;gBACG;aACD;QACH,CAAA;AAEJ,EAAE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
6
|
+
export default function migration(tree: Tree): Promise<MigrationReturnObject>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { getProjects, updateProjectConfiguration } from "@nx/devkit";
|
|
5
|
+
import { INFRA_APP_GENERATOR_INFO } from "../../../infra/app/generator.js";
|
|
6
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
7
|
+
/**
|
|
8
|
+
* Point the CDK infrastructure `checkov` target's cache inputs at the project
|
|
9
|
+
* rather than at the synth output directory.
|
|
10
|
+
*
|
|
11
|
+
* The target declared `["{workspaceRoot}/dist/{projectRoot}/cdk.out"]`, a
|
|
12
|
+
* fileset input. Nx resolves a fileset against the files it tracks, and `dist`
|
|
13
|
+
* is gitignored — so the input matched nothing and hashed to a constant. Once
|
|
14
|
+
* the scan had been cached, every later run was a hit: adding a non-compliant
|
|
15
|
+
* resource to a stack left `build` reporting success, and restored a
|
|
16
|
+
* `checkov_report.json` recording zero resources scanned.
|
|
17
|
+
*
|
|
18
|
+
* `["default"]` is what its `synth` sibling declares. It covers the project's
|
|
19
|
+
* own sources and carries the transitive `dependentTasksOutputFiles` entry from
|
|
20
|
+
* `nx.json`, which Nx resolves against the upstream `synth` task — so the hash
|
|
21
|
+
* follows the template the scan actually reads.
|
|
22
|
+
*/ const CHECKOV_TARGET = 'checkov';
|
|
23
|
+
/** The inputs the pre-fix generator declared, replaced in place. */ const VENDED_INPUTS = [
|
|
24
|
+
'{workspaceRoot}/dist/{projectRoot}/cdk.out'
|
|
25
|
+
];
|
|
26
|
+
/** The inputs the generator declares now, matching the `synth` sibling. */ const FIXED_INPUTS = [
|
|
27
|
+
'default'
|
|
28
|
+
];
|
|
29
|
+
const divergedMessage = (projectName)=>`${projectName}:${CHECKOV_TARGET}: its \`inputs\` have diverged from the generated shape - left untouched. Confirm they cover the synthesized template the scan reads: an input pointed only at \`dist\` matches no tracked file, so the scan can report a cached pass on infrastructure it never scanned.`;
|
|
30
|
+
/** Whether a target's inputs are exactly the ones the generator vended. */ const hasVendedInputs = (target)=>Array.isArray(target.inputs) && target.inputs.length === VENDED_INPUTS.length && target.inputs.every((input, index)=>input === VENDED_INPUTS[index]);
|
|
31
|
+
export default async function migration(tree) {
|
|
32
|
+
const nextSteps = [];
|
|
33
|
+
for (const [projectName, project] of getProjects(tree)){
|
|
34
|
+
const generator = project.metadata?.generator;
|
|
35
|
+
if (generator !== INFRA_APP_GENERATOR_INFO.id) continue;
|
|
36
|
+
const target = project.targets?.[CHECKOV_TARGET];
|
|
37
|
+
if (!target) continue;
|
|
38
|
+
// A target already declaring the fixed inputs needs nothing, which also
|
|
39
|
+
// makes a re-run — and a project generated after the fix — a no-op.
|
|
40
|
+
if (Array.isArray(target.inputs) && target.inputs.length === FIXED_INPUTS.length && target.inputs.every((input, index)=>input === FIXED_INPUTS[index])) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (!hasVendedInputs(target)) {
|
|
44
|
+
nextSteps.push(divergedMessage(projectName));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
target.inputs = [
|
|
48
|
+
...FIXED_INPUTS
|
|
49
|
+
];
|
|
50
|
+
updateProjectConfiguration(tree, projectName, project);
|
|
51
|
+
}
|
|
52
|
+
await formatFilesInSubtree(tree);
|
|
53
|
+
return {
|
|
54
|
+
nextSteps
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/checkov-scan-cache-inputs/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 type MigrationReturnObject,\n type ProjectConfiguration,\n type TargetConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { INFRA_APP_GENERATOR_INFO } from '../../../infra/app/generator.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\n\n/**\n * Point the CDK infrastructure `checkov` target's cache inputs at the project\n * rather than at the synth output directory.\n *\n * The target declared `[\"{workspaceRoot}/dist/{projectRoot}/cdk.out\"]`, a\n * fileset input. Nx resolves a fileset against the files it tracks, and `dist`\n * is gitignored — so the input matched nothing and hashed to a constant. Once\n * the scan had been cached, every later run was a hit: adding a non-compliant\n * resource to a stack left `build` reporting success, and restored a\n * `checkov_report.json` recording zero resources scanned.\n *\n * `[\"default\"]` is what its `synth` sibling declares. It covers the project's\n * own sources and carries the transitive `dependentTasksOutputFiles` entry from\n * `nx.json`, which Nx resolves against the upstream `synth` task — so the hash\n * follows the template the scan actually reads.\n */\n\nconst CHECKOV_TARGET = 'checkov';\n\n/** The inputs the pre-fix generator declared, replaced in place. */\nconst VENDED_INPUTS = ['{workspaceRoot}/dist/{projectRoot}/cdk.out'];\n\n/** The inputs the generator declares now, matching the `synth` sibling. */\nconst FIXED_INPUTS = ['default'];\n\nconst divergedMessage = (projectName: string) =>\n `${projectName}:${CHECKOV_TARGET}: its \\`inputs\\` have diverged from the generated shape - left untouched. Confirm they cover the synthesized template the scan reads: an input pointed only at \\`dist\\` matches no tracked file, so the scan can report a cached pass on infrastructure it never scanned.`;\n\n/** Whether a target's inputs are exactly the ones the generator vended. */\nconst hasVendedInputs = (target: TargetConfiguration): boolean =>\n Array.isArray(target.inputs) &&\n target.inputs.length === VENDED_INPUTS.length &&\n target.inputs.every((input, index) => input === VENDED_INPUTS[index]);\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n for (const [projectName, project] of getProjects(tree)) {\n const generator = (project.metadata as { generator?: string } | undefined)\n ?.generator;\n if (generator !== INFRA_APP_GENERATOR_INFO.id) continue;\n\n const target = project.targets?.[CHECKOV_TARGET];\n if (!target) continue;\n\n // A target already declaring the fixed inputs needs nothing, which also\n // makes a re-run — and a project generated after the fix — a no-op.\n if (\n Array.isArray(target.inputs) &&\n target.inputs.length === FIXED_INPUTS.length &&\n target.inputs.every((input, index) => input === FIXED_INPUTS[index])\n ) {\n continue;\n }\n\n if (!hasVendedInputs(target)) {\n nextSteps.push(divergedMessage(projectName));\n continue;\n }\n\n target.inputs = [...FIXED_INPUTS];\n updateProjectConfiguration(\n tree,\n projectName,\n project as ProjectConfiguration,\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","updateProjectConfiguration","INFRA_APP_GENERATOR_INFO","formatFilesInSubtree","CHECKOV_TARGET","VENDED_INPUTS","FIXED_INPUTS","divergedMessage","projectName","hasVendedInputs","target","Array","isArray","inputs","length","every","input","index","migration","tree","nextSteps","project","generator","metadata","id","targets","push"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EAKXC,0BAA0B,QACrB,aAAa;AACpB,SAASC,wBAAwB,QAAQ,kCAAkC;AAC3E,SAASC,oBAAoB,QAAQ,2BAA2B;AAEhE;;;;;;;;;;;;;;;CAeC,GAED,MAAMC,iBAAiB;AAEvB,kEAAkE,GAClE,MAAMC,gBAAgB;IAAC;CAA6C;AAEpE,yEAAyE,GACzE,MAAMC,eAAe;IAAC;CAAU;AAEhC,MAAMC,kBAAkB,CAACC,cACvB,GAAGA,YAAY,CAAC,EAAEJ,eAAe,yQAAyQ,CAAC;AAE7S,yEAAyE,GACzE,MAAMK,kBAAkB,CAACC,SACvBC,MAAMC,OAAO,CAACF,OAAOG,MAAM,KAC3BH,OAAOG,MAAM,CAACC,MAAM,KAAKT,cAAcS,MAAM,IAC7CJ,OAAOG,MAAM,CAACE,KAAK,CAAC,CAACC,OAAOC,QAAUD,UAAUX,aAAa,CAACY,MAAM;AAEtE,eAAe,eAAeC,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,KAAK,MAAM,CAACZ,aAAaa,QAAQ,IAAIrB,YAAYmB,MAAO;QACtD,MAAMG,YAAaD,QAAQE,QAAQ,EAC/BD;QACJ,IAAIA,cAAcpB,yBAAyBsB,EAAE,EAAE;QAE/C,MAAMd,SAASW,QAAQI,OAAO,EAAE,CAACrB,eAAe;QAChD,IAAI,CAACM,QAAQ;QAEb,wEAAwE;QACxE,oEAAoE;QACpE,IACEC,MAAMC,OAAO,CAACF,OAAOG,MAAM,KAC3BH,OAAOG,MAAM,CAACC,MAAM,KAAKR,aAAaQ,MAAM,IAC5CJ,OAAOG,MAAM,CAACE,KAAK,CAAC,CAACC,OAAOC,QAAUD,UAAUV,YAAY,CAACW,MAAM,GACnE;YACA;QACF;QAEA,IAAI,CAACR,gBAAgBC,SAAS;YAC5BU,UAAUM,IAAI,CAACnB,gBAAgBC;YAC/B;QACF;QAEAE,OAAOG,MAAM,GAAG;eAAIP;SAAa;QACjCL,2BACEkB,MACAX,aACAa;IAEJ;IAEA,MAAMlB,qBAAqBgB;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`gateway-url-accessor migration > should add the gatewayUrl accessor to the vended core construct 1`] = `
|
|
4
|
+
"import * as agentcore from 'aws-cdk-lib/aws-bedrockagentcore';
|
|
5
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
6
|
+
import { Construct } from 'constructs';
|
|
7
|
+
|
|
8
|
+
export class AgentCoreGateway extends Construct implements iam.IGrantable {
|
|
9
|
+
public readonly gateway: agentcore.Gateway;
|
|
10
|
+
|
|
11
|
+
constructor(scope: Construct, id: string) {
|
|
12
|
+
super(scope, id);
|
|
13
|
+
this.gateway = undefined as any;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The principal to grant permissions to.
|
|
18
|
+
*/
|
|
19
|
+
public get grantPrincipal(): iam.IPrincipal {
|
|
20
|
+
return this.gateway.role.grantPrincipal;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The gateway's URL endpoint. The Gateway L2 types its own \`gatewayUrl\` as
|
|
25
|
+
* optional and only populates it when created from its own props, so fall
|
|
26
|
+
* back to the CloudFormation attribute.
|
|
27
|
+
*/
|
|
28
|
+
public get gatewayUrl(): string {
|
|
29
|
+
return (
|
|
30
|
+
this.gateway.gatewayUrl ??
|
|
31
|
+
(this.gateway.node.defaultChild as agentcore.CfnGateway).attrGatewayUrl
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public addGateway(
|
|
36
|
+
gateway: Construct & {
|
|
37
|
+
readonly gateway: agentcore.Gateway;
|
|
38
|
+
readonly gatewayName: string;
|
|
39
|
+
readonly gatewayUrl: string;
|
|
40
|
+
},
|
|
41
|
+
props?: {
|
|
42
|
+
gatewayTargetName?: string;
|
|
43
|
+
},
|
|
44
|
+
): agentcore.CfnGatewayTarget {
|
|
45
|
+
const target = this.addGatewayTarget({
|
|
46
|
+
gatewayTargetName: props?.gatewayTargetName ?? gateway.gatewayName,
|
|
47
|
+
gatewayUrl: gateway.gatewayUrl,
|
|
48
|
+
gatewayArn: gateway.gateway.gatewayArn,
|
|
49
|
+
});
|
|
50
|
+
target.node.addDependency(gateway);
|
|
51
|
+
return target;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public addGatewayTarget(props: {
|
|
55
|
+
gatewayTargetName: string;
|
|
56
|
+
gatewayUrl: string;
|
|
57
|
+
gatewayArn: string;
|
|
58
|
+
}): agentcore.CfnGatewayTarget {
|
|
59
|
+
return undefined as any;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
"
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
exports[`gateway-url-accessor migration > should point vended app-level gateway constructs at the accessor 1`] = `
|
|
66
|
+
"import { Construct } from 'constructs';
|
|
67
|
+
import { AgentCoreGateway } from '../../../core/agentcore-gateway/agentcore-gateway';
|
|
68
|
+
import { RuntimeConfig } from '../../../core/runtime-config';
|
|
69
|
+
|
|
70
|
+
export class MyGateway extends AgentCoreGateway {
|
|
71
|
+
public readonly gatewayName = 'my-gateway';
|
|
72
|
+
|
|
73
|
+
constructor(scope: Construct, id: string) {
|
|
74
|
+
super(scope, id);
|
|
75
|
+
|
|
76
|
+
const rc = RuntimeConfig.ensure(this);
|
|
77
|
+
rc.set('agentcore', 'gateways', {
|
|
78
|
+
...rc.get('agentcore').gateways,
|
|
79
|
+
MyGateway: this.gatewayUrl,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
"
|
|
84
|
+
`;
|
|
@@ -0,0 +1,94 @@
|
|
|
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
|
+
* The CDK `Gateway` L2 types its `gatewayUrl` as `string | undefined`, so
|
|
9
|
+
* reaching through the vended `AgentCoreGateway` construct to
|
|
10
|
+
* `gateway.gateway.gatewayUrl` does not typecheck where a `string` is required —
|
|
11
|
+
* the DCR proxy's `upstreamUrl`, for example. `AgentCoreGateway` gains a
|
|
12
|
+
* non-optional `gatewayUrl` accessor falling back to the CloudFormation
|
|
13
|
+
* attribute, which `addGateway` and the vended app-level gateway constructs then
|
|
14
|
+
* read.
|
|
15
|
+
*/ const CONSTRUCTS_SRC = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src`;
|
|
16
|
+
const GATEWAY_CONSTRUCT_FILE = `${CONSTRUCTS_SRC}/core/agentcore-gateway/agentcore-gateway.ts`;
|
|
17
|
+
const GATEWAYS_DIR = `${CONSTRUCTS_SRC}/app/gateways`;
|
|
18
|
+
const GATEWAY_URL_ACCESSOR = `/**
|
|
19
|
+
* The gateway's URL endpoint. The Gateway L2 types its own \`gatewayUrl\` as
|
|
20
|
+
* optional and only populates it when created from its own props, so fall
|
|
21
|
+
* back to the CloudFormation attribute.
|
|
22
|
+
*/
|
|
23
|
+
public get gatewayUrl(): string {
|
|
24
|
+
return (
|
|
25
|
+
this.gateway.gatewayUrl ??
|
|
26
|
+
(this.gateway.node.defaultChild as agentcore.CfnGateway).attrGatewayUrl
|
|
27
|
+
);
|
|
28
|
+
}`;
|
|
29
|
+
const divergedCoreMessage = `${GATEWAY_CONSTRUCT_FILE}: the AgentCoreGateway construct has diverged from the generated shape - left untouched. To use a gateway's URL where a \`string\` is required, add a \`public get gatewayUrl(): string\` accessor returning \`this.gateway.gatewayUrl ?? (this.gateway.node.defaultChild as agentcore.CfnGateway).attrGatewayUrl\`.`;
|
|
30
|
+
/**
|
|
31
|
+
* Add the `gatewayUrl` accessor to the vended core construct, and route
|
|
32
|
+
* `addGateway` and the shape it requires of its argument through it. Returns
|
|
33
|
+
* whether the core construct ends up carrying the accessor — app-level
|
|
34
|
+
* constructs may only be pointed at it once it exists.
|
|
35
|
+
*/ const migrateCoreConstruct = async (tree, nextSteps)=>{
|
|
36
|
+
if (!tree.exists(GATEWAY_CONSTRUCT_FILE)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const hasAccessor = await matchGritQL(tree, GATEWAY_CONSTRUCT_FILE, '`public get gatewayUrl(): string { $_ }`');
|
|
40
|
+
if (!hasAccessor) {
|
|
41
|
+
// Anchored on the grantPrincipal accessor, present in every vended version.
|
|
42
|
+
const added = await insertViaGritQL(tree, GATEWAY_CONSTRUCT_FILE, `\`public get grantPrincipal(): iam.IPrincipal { $body }\` as $accessor => \`$accessor
|
|
43
|
+
|
|
44
|
+
${GRIT_INSERT_PLACEHOLDER}\``, GATEWAY_URL_ACCESSOR);
|
|
45
|
+
if (!added) {
|
|
46
|
+
nextSteps.push(divergedCoreMessage);
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const addGatewayUsesAccessor = await matchGritQL(tree, GATEWAY_CONSTRUCT_FILE, '`gatewayUrl: gateway.gatewayUrl`');
|
|
51
|
+
if (!addGatewayUsesAccessor) {
|
|
52
|
+
// The accessor is part of the shape addGateway requires of its argument.
|
|
53
|
+
await applyGritQL(tree, GATEWAY_CONSTRUCT_FILE, `\`readonly gatewayName: string\` as $member => \`$member;
|
|
54
|
+
readonly gatewayUrl: string\``);
|
|
55
|
+
// addGateway reads the accessor rather than repeating the fallback inline.
|
|
56
|
+
await applyGritQL(tree, GATEWAY_CONSTRUCT_FILE, `\`this.addGatewayTarget({ gatewayTargetName: $name, gatewayUrl: $url, gatewayArn: $arn })\` where {
|
|
57
|
+
$url <: contains \`attrGatewayUrl\`
|
|
58
|
+
} => \`this.addGatewayTarget({
|
|
59
|
+
gatewayTargetName: $name,
|
|
60
|
+
gatewayUrl: gateway.gatewayUrl,
|
|
61
|
+
gatewayArn: $arn,
|
|
62
|
+
})\``);
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Point each vended app-level gateway construct's runtime config entry at the
|
|
68
|
+
* accessor.
|
|
69
|
+
*/ const migrateAppConstructs = async (tree)=>{
|
|
70
|
+
if (!tree.exists(GATEWAYS_DIR)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
for (const dir of tree.children(GATEWAYS_DIR)){
|
|
74
|
+
const constructFile = `${GATEWAYS_DIR}/${dir}/${dir}.ts`;
|
|
75
|
+
if (!tree.exists(constructFile)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
await applyGritQL(tree, constructFile, '`this.gateway.gatewayUrl` => `this.gatewayUrl`');
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
export default async function migration(tree) {
|
|
82
|
+
const nextSteps = [];
|
|
83
|
+
// The app constructs read the accessor, so they may only be migrated once the
|
|
84
|
+
// core construct carries it.
|
|
85
|
+
if (await migrateCoreConstruct(tree, nextSteps)) {
|
|
86
|
+
await migrateAppConstructs(tree);
|
|
87
|
+
}
|
|
88
|
+
await formatFilesInSubtree(tree);
|
|
89
|
+
return {
|
|
90
|
+
nextSteps
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/gateway-url-accessor/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.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n} from '../../../utils/shared-constructs-constants.js';\n\n/**\n * The CDK `Gateway` L2 types its `gatewayUrl` as `string | undefined`, so\n * reaching through the vended `AgentCoreGateway` construct to\n * `gateway.gateway.gatewayUrl` does not typecheck where a `string` is required —\n * the DCR proxy's `upstreamUrl`, for example. `AgentCoreGateway` gains a\n * non-optional `gatewayUrl` accessor falling back to the CloudFormation\n * attribute, which `addGateway` and the vended app-level gateway constructs then\n * read.\n */\n\nconst CONSTRUCTS_SRC = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src`;\n\nconst GATEWAY_CONSTRUCT_FILE = `${CONSTRUCTS_SRC}/core/agentcore-gateway/agentcore-gateway.ts`;\n\nconst GATEWAYS_DIR = `${CONSTRUCTS_SRC}/app/gateways`;\n\nconst GATEWAY_URL_ACCESSOR = `/**\n * The gateway's URL endpoint. The Gateway L2 types its own \\`gatewayUrl\\` as\n * optional and only populates it when created from its own props, so fall\n * back to the CloudFormation attribute.\n */\n public get gatewayUrl(): string {\n return (\n this.gateway.gatewayUrl ??\n (this.gateway.node.defaultChild as agentcore.CfnGateway).attrGatewayUrl\n );\n }`;\n\nconst divergedCoreMessage = `${GATEWAY_CONSTRUCT_FILE}: the AgentCoreGateway construct has diverged from the generated shape - left untouched. To use a gateway's URL where a \\`string\\` is required, add a \\`public get gatewayUrl(): string\\` accessor returning \\`this.gateway.gatewayUrl ?? (this.gateway.node.defaultChild as agentcore.CfnGateway).attrGatewayUrl\\`.`;\n\n/**\n * Add the `gatewayUrl` accessor to the vended core construct, and route\n * `addGateway` and the shape it requires of its argument through it. Returns\n * whether the core construct ends up carrying the accessor — app-level\n * constructs may only be pointed at it once it exists.\n */\nconst migrateCoreConstruct = async (\n tree: Tree,\n nextSteps: string[],\n): Promise<boolean> => {\n if (!tree.exists(GATEWAY_CONSTRUCT_FILE)) {\n return false;\n }\n\n const hasAccessor = await matchGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n '`public get gatewayUrl(): string { $_ }`',\n );\n\n if (!hasAccessor) {\n // Anchored on the grantPrincipal accessor, present in every vended version.\n const added = await insertViaGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n `\\`public get grantPrincipal(): iam.IPrincipal { $body }\\` as $accessor => \\`$accessor\n\n ${GRIT_INSERT_PLACEHOLDER}\\``,\n GATEWAY_URL_ACCESSOR,\n );\n if (!added) {\n nextSteps.push(divergedCoreMessage);\n return false;\n }\n }\n\n const addGatewayUsesAccessor = await matchGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n '`gatewayUrl: gateway.gatewayUrl`',\n );\n\n if (!addGatewayUsesAccessor) {\n // The accessor is part of the shape addGateway requires of its argument.\n await applyGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n `\\`readonly gatewayName: string\\` as $member => \\`$member;\n readonly gatewayUrl: string\\``,\n );\n\n // addGateway reads the accessor rather than repeating the fallback inline.\n await applyGritQL(\n tree,\n GATEWAY_CONSTRUCT_FILE,\n `\\`this.addGatewayTarget({ gatewayTargetName: $name, gatewayUrl: $url, gatewayArn: $arn })\\` where {\n $url <: contains \\`attrGatewayUrl\\`\n} => \\`this.addGatewayTarget({\n gatewayTargetName: $name,\n gatewayUrl: gateway.gatewayUrl,\n gatewayArn: $arn,\n })\\``,\n );\n }\n\n return true;\n};\n\n/**\n * Point each vended app-level gateway construct's runtime config entry at the\n * accessor.\n */\nconst migrateAppConstructs = async (tree: Tree): Promise<void> => {\n if (!tree.exists(GATEWAYS_DIR)) {\n return;\n }\n for (const dir of tree.children(GATEWAYS_DIR)) {\n const constructFile = `${GATEWAYS_DIR}/${dir}/${dir}.ts`;\n if (!tree.exists(constructFile)) {\n continue;\n }\n await applyGritQL(\n tree,\n constructFile,\n '`this.gateway.gatewayUrl` => `this.gatewayUrl`',\n );\n }\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n // The app constructs read the accessor, so they may only be migrated once the\n // core construct carries it.\n if (await migrateCoreConstruct(tree, nextSteps)) {\n await migrateAppConstructs(tree);\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["applyGritQL","GRIT_INSERT_PLACEHOLDER","insertViaGritQL","matchGritQL","formatFilesInSubtree","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","CONSTRUCTS_SRC","GATEWAY_CONSTRUCT_FILE","GATEWAYS_DIR","GATEWAY_URL_ACCESSOR","divergedCoreMessage","migrateCoreConstruct","tree","nextSteps","exists","hasAccessor","added","push","addGatewayUsesAccessor","migrateAppConstructs","dir","children","constructFile","migration"],"mappings":"AAAA;;;CAGC,GAED,SACEA,WAAW,EACXC,uBAAuB,EACvBC,eAAe,EACfC,WAAW,QACN,wBAAwB;AAC/B,SAASC,oBAAoB,QAAQ,2BAA2B;AAChE,SACEC,YAAY,EACZC,qBAAqB,QAChB,gDAAgD;AAEvD;;;;;;;;CAQC,GAED,MAAMC,iBAAiB,GAAGF,aAAa,CAAC,EAAEC,sBAAsB,IAAI,CAAC;AAErE,MAAME,yBAAyB,GAAGD,eAAe,4CAA4C,CAAC;AAE9F,MAAME,eAAe,GAAGF,eAAe,aAAa,CAAC;AAErD,MAAMG,uBAAuB,CAAC;;;;;;;;;;GAU3B,CAAC;AAEJ,MAAMC,sBAAsB,GAAGH,uBAAuB,oTAAoT,CAAC;AAE3W;;;;;CAKC,GACD,MAAMI,uBAAuB,OAC3BC,MACAC;IAEA,IAAI,CAACD,KAAKE,MAAM,CAACP,yBAAyB;QACxC,OAAO;IACT;IAEA,MAAMQ,cAAc,MAAMb,YACxBU,MACAL,wBACA;IAGF,IAAI,CAACQ,aAAa;QAChB,4EAA4E;QAC5E,MAAMC,QAAQ,MAAMf,gBAClBW,MACAL,wBACA,CAAC;;EAEL,EAAEP,wBAAwB,EAAE,CAAC,EACzBS;QAEF,IAAI,CAACO,OAAO;YACVH,UAAUI,IAAI,CAACP;YACf,OAAO;QACT;IACF;IAEA,MAAMQ,yBAAyB,MAAMhB,YACnCU,MACAL,wBACA;IAGF,IAAI,CAACW,wBAAwB;QAC3B,yEAAyE;QACzE,MAAMnB,YACJa,MACAL,wBACA,CAAC;mCAC4B,CAAC;QAGhC,2EAA2E;QAC3E,MAAMR,YACJa,MACAL,wBACA,CAAC;;;;;;QAMC,CAAC;IAEP;IAEA,OAAO;AACT;AAEA;;;CAGC,GACD,MAAMY,uBAAuB,OAAOP;IAClC,IAAI,CAACA,KAAKE,MAAM,CAACN,eAAe;QAC9B;IACF;IACA,KAAK,MAAMY,OAAOR,KAAKS,QAAQ,CAACb,cAAe;QAC7C,MAAMc,gBAAgB,GAAGd,aAAa,CAAC,EAAEY,IAAI,CAAC,EAAEA,IAAI,GAAG,CAAC;QACxD,IAAI,CAACR,KAAKE,MAAM,CAACQ,gBAAgB;YAC/B;QACF;QACA,MAAMvB,YACJa,MACAU,eACA;IAEJ;AACF;AAEA,eAAe,eAAeC,UAC5BX,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,8EAA8E;IAC9E,6BAA6B;IAC7B,IAAI,MAAMF,qBAAqBC,MAAMC,YAAY;QAC/C,MAAMM,qBAAqBP;IAC7B;IAEA,MAAMT,qBAAqBS;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Deploy using CloudFormation express mode from the deploy
|
|
2
|
+
"description": "Deploy using CloudFormation express mode from the deploy-sandbox target of ts#infra projects, and wait for full stabilization from deploy"
|
|
3
3
|
}
|
|
@@ -5,29 +5,31 @@
|
|
|
5
5
|
import { INFRA_APP_GENERATOR_INFO } from "../../../infra/app/generator.js";
|
|
6
6
|
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
7
7
|
/**
|
|
8
|
-
* Deploy using CloudFormation express mode from the deploy
|
|
9
|
-
*
|
|
8
|
+
* Deploy using CloudFormation express mode from the deploy-sandbox target of
|
|
9
|
+
* ts#infra projects, and wait for full stabilization everywhere else.
|
|
10
10
|
*
|
|
11
|
-
* Express mode completes each resource operation as soon as its configuration
|
|
12
|
-
*
|
|
13
|
-
* iteration cycle for development deploys.
|
|
11
|
+
* Express mode completes each resource operation as soon as its configuration is
|
|
12
|
+
* applied rather than waiting for full stabilization, which is a much faster
|
|
13
|
+
* iteration cycle for development deploys. It returns before resources have
|
|
14
|
+
* settled, so it suits only the stage you iterate on.
|
|
14
15
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*/ const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
* `deploy-sandbox` therefore gets it, since it only ever deploys the sandbox
|
|
17
|
+
* stage. `deploy` names whichever stage you give it, including beta and prod, and
|
|
18
|
+
* `deploy-ci` runs from a pipeline - both wait for full stabilization.
|
|
19
|
+
*/ const EXPRESS_FLAG = '--express';
|
|
20
|
+
const NO_EXPRESS_FLAG = '--no-express';
|
|
21
|
+
/** Whether `deploy-sandbox` should carry the flag, and `deploy` should not. */ const WANTS_EXPRESS = {
|
|
22
|
+
'deploy-sandbox': true,
|
|
23
|
+
deploy: false
|
|
24
|
+
};
|
|
23
25
|
/**
|
|
24
26
|
* Whether the command is one of the deploy commands this migration vends -
|
|
25
27
|
* either a direct `cdk deploy`, or the stage-config `infra-deploy.ts` script
|
|
26
28
|
* that wraps it. Anything else has been hand-written and is reported rather
|
|
27
29
|
* than rewritten.
|
|
28
30
|
*/ const isGeneratedDeployCommand = (command)=>/(^|\s)cdk\s+deploy(\s|$)/.test(command) || command.includes('infra-deploy.ts');
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
const divergedNextStep = (projectName, target, wantsExpress)=>wantsExpress ? `${projectName}: its ${target} target has been customised, so it was left as it is. Add "${EXPRESS_FLAG}" to the target's command to deploy using CloudFormation express mode.` : `${projectName}: its ${target} target has been customised, so it was left as it is. Remove "${EXPRESS_FLAG}" from the target's command so it waits for full resource stabilization - this target can name any stage, including production.`;
|
|
32
|
+
/** Drops the flag wherever it sits, leaving the rest of the command untouched. */ const withoutExpress = (command)=>command.split(/\s+/).filter((arg)=>arg !== EXPRESS_FLAG).join(' ');
|
|
31
33
|
export default async function migration(tree) {
|
|
32
34
|
const nextSteps = [];
|
|
33
35
|
let migrated = false;
|
|
@@ -36,35 +38,31 @@ export default async function migration(tree) {
|
|
|
36
38
|
continue;
|
|
37
39
|
}
|
|
38
40
|
let projectChanged = false;
|
|
39
|
-
for (const targetName of
|
|
41
|
+
for (const [targetName, wantsExpress] of Object.entries(WANTS_EXPRESS)){
|
|
40
42
|
const target = project.targets?.[targetName];
|
|
41
43
|
const command = target?.options?.command;
|
|
42
44
|
if (!target || typeof command !== 'string') {
|
|
43
45
|
continue;
|
|
44
46
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
const args = command.split(/\s+/);
|
|
48
|
+
const hasExpress = args.includes(EXPRESS_FLAG);
|
|
49
|
+
// Already in the wanted state, so re-running - and a project generated
|
|
50
|
+
// after this change - is a no-op.
|
|
51
|
+
if (hasExpress === wantsExpress) {
|
|
48
52
|
continue;
|
|
49
53
|
}
|
|
50
54
|
// `--no-express` is a deliberate opt-out, so honour it rather than
|
|
51
55
|
// flipping the user back to express mode.
|
|
52
|
-
if (
|
|
56
|
+
if (wantsExpress && args.includes(NO_EXPRESS_FLAG)) {
|
|
53
57
|
continue;
|
|
54
58
|
}
|
|
55
59
|
if (!isGeneratedDeployCommand(command)) {
|
|
56
|
-
nextSteps.push(divergedNextStep(name, targetName));
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
// When stages are configured, `deploy` deploys whichever stage is named,
|
|
60
|
-
// including beta and prod, so it stays on full stabilization. Only its
|
|
61
|
-
// sandbox counterpart opts into express mode.
|
|
62
|
-
if (targetName === 'deploy' && isStageConfigDeploy(command)) {
|
|
60
|
+
nextSteps.push(divergedNextStep(name, targetName, wantsExpress));
|
|
63
61
|
continue;
|
|
64
62
|
}
|
|
65
63
|
// Appended last so it stays clear of the stage pattern, which the
|
|
66
64
|
// stage-config deploy script reads from the first positional argument.
|
|
67
|
-
target.options.command = `${command} ${EXPRESS_FLAG}
|
|
65
|
+
target.options.command = wantsExpress ? `${command} ${EXPRESS_FLAG}` : withoutExpress(command);
|
|
68
66
|
projectChanged = true;
|
|
69
67
|
}
|
|
70
68
|
if (projectChanged) {
|