Skip to content

Jack

3 posts by Jack

AWS PDKからの移行

このガイドでは、AWS PDKプロジェクトをNx Plugin for AWSに移行する例を説明し、このトピックに関する一般的なガイダンスを提供します。

Nx Plugin for AWSへの移行により、PDKと比較して以下のメリットが得られます:

  • より高速なビルド
  • より使いやすい(UIとCLI)
  • Vibe-codingフレンドリー(MCPサーバーをお試しください!
  • より最新のテクノロジー
  • ローカルAPIとウェブサイト開発
  • より多くの制御(ユースケースに合わせて提供されたファイルを変更可能)
  • その他多数!

移行例:ショッピングリストアプリケーション

Section titled “移行例:ショッピングリストアプリケーション”

このガイドでは、PDKチュートリアルのショッピングリストアプリケーションを移行対象プロジェクトとして使用します。ご自身で実際に試す場合は、そのチュートリアルの手順に従って対象プロジェクトを作成してください。

ショッピングリストアプリケーションは、以下のPDKプロジェクトタイプで構成されています:

  • MonorepoTsProject
  • TypeSafeApiProject
  • CloudscapeReactTsWebsiteProject
  • InfrastructureTsProject

まず、新しいプロジェクト用の新しいワークスペースを作成します。インプレース移行よりも極端ですが、このアプローチにより最もクリーンな最終結果が得られます。Nxワークスペースの作成は、PDKのMonorepoTsProjectの使用と同等です:

Terminal window
pnpm create @aws/nx-workspace@1.0.0-rc.47 shopping-list --iac=cdk

このコマンドで作成されたshopping-listディレクトリをお気に入りのIDEで開きます。

ショッピングリストアプリケーションで使用されている TypeSafeApiProject は、以下を利用していました:

  • モデリング言語として Smithy
  • オペレーションの実装にTypeScript
  • Reactウェブサイトとの統合のためのTypeScriptフック生成

したがって、ts#smithy-api ジェネレーターを使用して同等の機能を提供できます。

ts#api ジェネレーターframeworksmithy に設定して実行し、packages/api にAPIプロジェクトをセットアップします:

Terminal window
pnpm nx g @aws/nx-plugin:ts#api --name=api --framework=smithy --namespace=com.aws --auth=iam --no-interactive
変更されるファイルを確認するためにドライランを実行することもできます
Terminal window
pnpm nx g @aws/nx-plugin:ts#api --name=api --framework=smithy --namespace=com.aws --auth=iam --no-interactive --dry-run

これにより、model プロジェクトと backend プロジェクトが生成されることがわかります。model プロジェクトにはSmithyモデルが含まれ、backend にはサーバー実装が含まれます。

バックエンドは Smithy Server Generator for TypeScript を使用します。これについては以下でさらに詳しく説明します。

Smithy APIプロジェクトの基本構造ができたので、モデルを移行できます:

  1. packages/api/model/src にある生成されたサンプルSmithyファイルを削除します

  2. PDKプロジェクトの packages/api/model/src/main/smithy ディレクトリからモデルを新しいプロジェクトの packages/api/model/src ディレクトリにコピーします。

  3. smithy-build.json のサービス名と名前空間をPDKアプリケーションに合わせて更新します:

    smithy-build.json
    "plugins": {
    "openapi": {
    "service": "com.aws#MyApi",
    ...
  4. main.smithy のサービスを更新して ValidationException エラーを追加します。これはSmithy TypeScript Server SDKを使用する際に必要です。

    main.smithy
    use smithy.framework#ValidationException
    /// My Shopping List API
    @restJson1
    service MyApi {
    version: "1.0"
    operations: [
    GetShoppingLists
    PutShoppingList
    DeleteShoppingList
    ]
    errors: [
    BadRequestError
    NotAuthorizedError
    InternalFailureError
    ValidationException
    ]
    }
  5. packages/api/model/srcextensions.smithy ファイルを追加し、生成されたクライアントにページネーション情報を提供するトレイトを定義します:

    extensions.smithy
    $version: "2"
    namespace com.aws
    use smithy.openapi#specificationExtension
    @trait
    @specificationExtension(as: "x-cursor")
    structure cursor {
    inputToken: String
    enabled: Boolean
    }
  6. get-shopping-lists.smithyGetShoppingLists オペレーションに新しい @cursor トレイトを追加します:

    operations/get-shopping-lists.smithy
    @readonly
    @http(method: "GET", uri: "/shopping-list")
    @paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "pageSize", items: "shoppingLists")
    @cursor(inputToken: "nextToken")
    @handler(language: "typescript")
    operation GetShoppingLists {
    input := with [PaginatedInputMixin] {
    @httpQuery("shoppingListId")
    shoppingListId: ShoppingListId
    }

    Nx Plugin for AWSが提供するクライアントジェネレーター(api-connection ジェネレーター経由)を使用している場合、@paginated オペレーションは @cursor も使用する必要があります。

  7. 最後に、すべてのオペレーションから @handler トレイトを削除します。これはNx Plugin for AWSではサポートされていません。ts#smithy-api を使用する場合、このトレイトによって生成される自動生成されたLambda関数のCDKコンストラクトとバンドリングターゲットは必要ありません。すべてのLambda関数に対して単一のバンドルを使用するためです。

この時点で、ビルドを実行してモデルの変更を確認し、作業用の生成されたサーバーコードがあることを確認しましょう。バックエンドプロジェクト(@shopping-list/api)でいくつかの失敗が発生しますが、次にそれらに対処します。

Terminal window
pnpm nx run-many --target build

api/backend プロジェクトは、Type Safe APIの api/handlers/typescript プロジェクトとある程度同等と考えることができます。

Type Safe APIと ts#smithy-api ジェネレーターの主な違いの1つは、ハンドラーがType Safe API独自の生成されたハンドラーラッパー(api/generated/typescript/runtime プロジェクトにあります)ではなく、Smithy Server Generator for TypeScript を使用して実装されることです。

ショッピングリストアプリケーションのLambdaハンドラーは @aws-sdk/client-dynamodb パッケージに依存しているため、@shopping-list/api プロジェクトにインストールしましょう:

Terminal window
pnpm add @aws-sdk/client-dynamodb --filter api

次に、PDKプロジェクトから handlers/src/dynamo-client.ts ファイルを backend/src/operations にコピーして、ハンドラーで使用できるようにします。

ts#smithy-api ジェネレーターは、サンプルの Echo オペレーションをスキャフォールドします。モデルからこれを削除したので、backend/src/operations/echo.ts の対応するハンドラーを削除します。移行したオペレーションは、以下の service.ts で登録します。

ハンドラーを移行するには、次の一般的な手順に従います:

  1. PDKプロジェクトの packages/api/handlers/typescript/src ディレクトリから新しいプロジェクトの packages/api/backend/src/operations ディレクトリにハンドラーをコピーします。

  2. my-api-typescript-runtime のインポートを削除し、代わりに生成されたTypeScript Server SDKからオペレーションタイプと ServiceContext をインポートします。例:

    import {
    deleteShoppingListHandler,
    DeleteShoppingListChainedHandlerFunction,
    INTERCEPTORS,
    Response,
    LoggingInterceptor,
    } from 'myapi-typescript-runtime';
    import { DeleteShoppingList as DeleteShoppingListOperation } from '../generated/ssdk/index.js';
    import { ServiceContext } from '../context.js';
  3. ハンドラーラッパーのエクスポートを削除します

    export const handler = deleteShoppingListHandler(
    ...INTERCEPTORS,
    deleteShoppingList,
    );
  4. オペレーションハンドラーのシグネチャをSSDKを使用するように更新します:

    export const deleteShoppingList: DeleteShoppingListChainedHandlerFunction = async (request) => {
    export const DeleteShoppingList: DeleteShoppingListOperation<ServiceContext> = async (input, ctx) => {
  5. LoggingInterceptor の使用を ctx.logger に置き換えます。(メトリクスとトレーシングのインターセプターにも適用されます):

    LoggingInterceptor.getLogger(request).info('...');
    ctx.logger.info('...');
  6. 入力パラメータへの参照を更新します。SSDKはSmithyモデルと正確に一致する型を提供するため(パス/クエリ/ヘッダーパラメータをボディパラメータとは別にグループ化するのではなく)、入力参照を適切に更新します:

    const shoppingListId = request.input.requestParameters.shoppingListId;
    const shoppingListId = input.shoppingListId;
  7. Response の使用を削除します。代わりに、SSDKでは単純なオブジェクトを返します。

    return Response.success({ shoppingListId });
    return { shoppingListId };

    また、Response をスローまたは返すことはなくなり、代わりにSSDKの生成されたエラーをスローします:

    throw Response.badRequest({ message: 'oh no' });
    return Response.badRequest({ message: 'oh no' });
    import { BadRequestError } from '../generated/ssdk/index.js';
    throw new BadRequestError({ message: 'oh no' });
  8. すべてのインポートをESM構文を使用するように更新します。つまり、相対インポートに .js 拡張子を追加します。

  9. service.ts にオペレーションを追加します

    service.ts
    import { ServiceContext } from './context.js';
    import { MyApiService } from './generated/ssdk/index.js';
    import { DeleteShoppingList } from './operations/delete-shopping-list.js';
    import { GetShoppingLists } from './operations/get-shopping-lists.js';
    import { PutShoppingList } from './operations/put-shopping-list.js';
    // Register operations to the service here
    export const Service: MyApiService<ServiceContext> = {
    PutShoppingList,
    GetShoppingLists,
    DeleteShoppingList,
    };
チュートリアルの3つのショッピングリストオペレーションの完全な移行前後の例については、ここをクリックしてください

最初に api という名前でSmithy APIプロジェクトを生成したのは、PDKプロジェクトとの一貫性のために packages/api に追加したかったためです。Smithy APIが service Api ではなく service MyApi を定義するようになったため、getApiServiceHandler のすべてのインスタンスを getMyApiServiceHandler に更新する必要があります。

handler.ts にこの変更を加えます:

packages/api/backend/src/handler.ts
import { getApiServiceHandler } from './generated/ssdk/index.js';
import { getMyApiServiceHandler } from './generated/ssdk/index.js';
process.env.POWERTOOLS_METRICS_NAMESPACE = 'Api';
process.env.POWERTOOLS_SERVICE_NAME = 'Api';
const tracer = new Tracer();
const logger = new Logger();
const metrics = new Metrics();
const serviceHandler = getApiServiceHandler(Service);
const serviceHandler = getMyApiServiceHandler(Service);

そして local-server.ts にも:

packages/api/backend/src/local-server.ts
import { getApiServiceHandler } from './generated/ssdk/index.js';
import { getMyApiServiceHandler } from './generated/ssdk/index.js';
const PORT = 3001;
const tracer = new Tracer();
const logger = new Logger();
const metrics = new Metrics();
const serviceHandler = getApiServiceHandler(Service);
const serviceHandler = getMyApiServiceHandler(Service);

さらに、packages/api/backend/project.json を更新し、metadata.apiNamemy-api に更新します:

packages/api/backend/project.json
"metadata": {
"generator": "ts#smithy-api",
"apiName": "api",
"apiName": "my-api",
"auth": "iam",
"modelProject": "@shopping-list/api-model",
"ports": [3001]
},

これで、プロジェクトをビルドして、これまでの移行が機能していることを確認できます:

Terminal window
pnpm nx run-many --target build

ショッピングリストアプリケーションで使用されている CloudscapeReactTsWebsiteProject は、CloudScape と Cognito 認証が組み込まれた React ウェブサイトを構成していました。

このプロジェクトタイプは create-react-app を活用していましたが、これは現在非推奨となっています。このガイドでウェブサイトを移行するために、より現代的でサポートされている技術、すなわち Vite を使用する ts#website ジェネレーター を使用します。

移行の一環として、PDK で構成された React Router から TanStack Router に移行します。これにより、ウェブサイトのルーティングに追加の型安全性が加わります。

ts#website ジェネレーターframeworkreact に設定して実行し、packages/website にウェブサイトプロジェクトをセットアップします。ショッピングリストアプリケーションは CloudScape コンポーネントで構築されているため、uxcloudscape に設定します(デフォルトは shadcn です):

Terminal window
pnpm nx g @aws/nx-plugin:ts#website --name=website --framework=react --ux=cloudscape --no-interactive
変更されるファイルを確認するためにドライランを実行することもできます
Terminal window
pnpm nx g @aws/nx-plugin:ts#website --name=website --framework=react --ux=cloudscape --no-interactive --dry-run

上記の React ウェブサイトジェネレーターは、CloudscapeReactTsWebsiteProject のようにデフォルトで cognito 認証をバンドルしていません。代わりに、ts#website#auth ジェネレーター を介して明示的に追加されます。

Terminal window
pnpm nx g @aws/nx-plugin:ts#website#auth --project=website --cognitoDomain=shopping-list --no-interactive
変更されるファイルを確認するためにドライランを実行することもできます
Terminal window
pnpm nx g @aws/nx-plugin:ts#website#auth --project=website --cognitoDomain=shopping-list --no-interactive --dry-run

これにより、Cognito ホストUI を使用してユーザーがログインするための適切なリダイレクトを管理する React コンポーネントが追加されます。また、packages/common/constructs に Cognito リソースをデプロイするための CDK コンストラクト(UserIdentity と呼ばれる)も追加されます。

PDK では、生成された Projen プロジェクトを相互に渡して統合コードを生成することができました。これは、ショッピングリストアプリケーションで、ウェブサイトが API と統合できるように構成するために使用されていました。

Nx Plugin for AWS では、API 統合は connection ジェネレーター を介してサポートされています。次に、このジェネレーターを使用して、ウェブサイトが Smithy API を呼び出せるようにします:

Terminal window
pnpm nx g @aws/nx-plugin:connection --sourceProject=website --targetProject=api --no-interactive
変更されるファイルを確認するためにドライランを実行することもできます
Terminal window
pnpm nx g @aws/nx-plugin:connection --sourceProject=website --targetProject=api --no-interactive --dry-run

これにより、生成された TypeScript クライアントを介してウェブサイトが API を呼び出すために必要なクライアントプロバイダーとビルドターゲットが生成されます。

CloudscapeReactTsWebsiteProject は、ショッピングリストアプリケーションで使用されている @aws-northstar/ui への依存関係を自動的に含んでいたため、@shopping-list/website プロジェクトに追加します:

Terminal window
pnpm add @aws-northstar/ui --filter website

@aws-northstar/ui は、ace-builds に依存するコードエディターコンポーネントをバンドルしており、Vite が解決できない webpack 固有のインポートを使用しています。ショッピングリストアプリケーションではこのコンポーネントを使用していないため、packages/website/vite.config.mts の既存の build オプション内の external 設定に追加してバンドルから除外します:

packages/website/vite.config.mts
build: {
outDir: '../../dist/packages/website/bundle',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
rollupOptions: {
external: ['ace-builds/webpack-resolver'],
},
},

コンポーネントとページの移動

Section titled “コンポーネントとページの移動”

ショッピングリストアプリケーション には、CreateItem というコンポーネントが1つと、ShoppingListShoppingLists という2つのページがあります。これらを新しいウェブサイトに移行し、TanStack Router と Nx Plugin for AWS TypeScript クライアントコードジェネレーターを使用しているため、いくつかの調整を行います。

  1. PDK プロジェクトから packages/website/src/components/CreateItem/index.tsx を新しいプロジェクトの全く同じ場所にコピーします。

  2. packages/website/src/pages/ShoppingLists/index.tsxpackages/website/src/routes/index.tsx にコピーします。ShoppingLists はホームページであり、TanStack router でファイルベースのルーティングを使用しているためです。

  3. packages/website/src/pages/ShoppingList/index.tsxpackages/website/src/routes/$shoppingListId.tsx にコピーします。ShoppingList/:shoppingListId ルートで表示したいページだったためです。

IDE でいくつかのビルドエラーが表示されるようになりますが、新しいフレームワークに適合させるためにさらにいくつかの変更を行う必要があります。以下で概説します。

React Router から TanStack Router への移行

Section titled “React Router から TanStack Router への移行”

ファイルベースルーティング を使用しているため、ウェブサイトのローカル開発サーバーを使用してルート設定を自動的に生成できます。

ローカルウェブサイトサーバーを起動しましょう:

Terminal window
pnpm nx dev website

いくつかのエラーが表示されますが、ローカルウェブサイトサーバーはポート 4200 で起動し、ローカル Smithy API サーバーはポート 3001 で起動するはずです。

routes/index.tsxroutes/$shoppingListId.tsx の両方で以下の手順に従って、TanStack Router に移行します:

  1. 各ルートを登録するためにcreateFileRouteを追加します:

    import { createFileRoute } from "@tanstack/react-router";
    ...
    export default ShoppingLists;
    export const Route = createFileRoute('/')({
    component: ShoppingLists,
    });

    ファイルを保存すると、createFileRoute の呼び出しに関する型エラーがなくなったことに気付くでしょう。

  2. useNavigate フックを置き換えます。

    インポートを更新します:

    import { useNavigate } from 'react-router-dom';
    import { useNavigate } from '@tanstack/react-router';

    navigate メソッド(useNavigate によって返される)の呼び出しを更新して、型安全なルートを渡すようにします:

    navigate(`/${cell.shoppingListId}`);
    navigate({
    to: '/$shoppingListId',
    params: { shoppingListId: cell.shoppingListId },
    });
  3. useParams フックを置き換えます。

    インポートを削除します:

    import { useParams } from 'react-router-dom';

    useParams の呼び出しを、上記で作成した Route によって提供されるフックで更新します。これらは型安全になりました!

    const { shoppingListId } = useParams();
    const { shoppingListId } = Route.useParams();

コンポーネントインポートの修正

Section titled “コンポーネントインポートの修正”

ルートファイルが PDK プロジェクトほどファイルツリーの深い位置にないため、routes/index.tsxroutes/$shoppingListId.tsx の両方で CreateItem のインポートを修正する必要があります:

import CreateItem from "../../components/CreateItem";
import CreateItem from "../components/CreateItem";

AppLayoutContext も新しいプロジェクトでは少し異なる場所で提供されています:

import { AppLayoutContext } from "../../layouts/App";
import { AppLayoutContext } from "../components/AppLayout";

新しい生成された TypeScript クライアントの使用への移行

Section titled “新しい生成された TypeScript クライアントの使用への移行”

もうすぐです!次に、Nx Plugin for AWS によって提供される TypeScript クライアントを使用するように移行する必要があります。これは Type Safe API と比較していくつかの改善があります。これを実現するには、以下の手順に従ってください

  1. 古いものの代わりに新しい生成されたクライアントと型をインポートします。例えば:

    import {
    ShoppingList,
    usePutShoppingList,
    useDeleteShoppingList,
    useGetShoppingLists,
    } from "myapi-typescript-react-query-hooks";
    import { ShoppingList } from "../generated/my-api/types.gen";
    import { useMyApi } from "../hooks/useMyApi";
    import { useInfiniteQuery, useMutation } from "@tanstack/react-query";

    routes/$shoppingListId.tsxShoppingList 型を _ShoppingList としてインポートしていることに注意してください - そのファイルでも同じようにしますが、再び types.gen からインポートします。

    また、生成されたクライアントはフックラッパーではなく、TanStack query フックのオプションを生成するメソッドを提供するため、関連するフックを @tanstack/react-query から直接インポートすることにも注意してください。

  2. 新しい TanStack Query フックをインスタンス化します。例えば:

    const getShoppingLists = useGetShoppingLists({ pageSize: PAGE_SIZE });
    const putShoppingList = usePutShoppingList();
    const deleteShoppingList = useDeleteShoppingList();
    const api = useMyApi();
    const getShoppingLists = useInfiniteQuery(
    api.getShoppingLists.infiniteQueryOptions(
    { pageSize: PAGE_SIZE },
    { getNextPageParam: (p) => p.nextToken },
    ),
    );
    const putShoppingList = useMutation(api.putShoppingList.mutationOptions());
    const deleteShoppingList = useMutation(
    api.deleteShoppingList.mutationOptions(),
    );
  3. リクエストボディでパラメータを受け入れる操作の呼び出しで、ラッパー <operation>RequestContent を削除します:

    await putShoppingList.mutateAsync({
    putShoppingListRequestContent: {
    name: item,
    },
    });

TanStack Query v4(PDK で使用)と、connection ジェネレーターが追加した v5 の違いにより、修正すべきエラーがいくつか残っています:

  1. ミューテーションの isLoadingisPending に置き換えます。例えば:

    putShoppingList.isLoading
    putShoppingList.isPending
  2. ショッピングリストアプリケーションは、TanStack Query v4 の型を期待する @aws-northstar/uiInfiniteQueryTable を使用していました。これは実際には v5 の無限クエリでも動作するため、型エラーを抑制するだけで済みます:

    <InfiniteQueryTable
    query={getShoppingLists}
    query={getShoppingLists as any}

ローカルウェブサイトへのアクセス

Section titled “ローカルウェブサイトへのアクセス”

http://localhost:4200/ でローカルウェブサイトにアクセスできるようになりました

すべてが移行されたので、ウェブサイトが読み込まれるはずです!ショッピングリストアプリケーションが API、Website、Identity 以外に依存しているインフラストラクチャは DynamoDB テーブルだけなので、リージョン内に shopping_list という名前の DynamoDB テーブルがあり、それにアクセスできるローカル AWS 認証情報があれば、ウェブサイトは完全に機能します!

そうでない場合でも大丈夫です。次にインフラストラクチャを移行します。

チュートリアルの2つのショッピングリストページの完全な変更前後の例については、ここをクリックしてください

ショッピングリストアプリケーションで移行する必要がある最後のプロジェクトは InfrastructureTsProject です。これは TypeScript CDK プロジェクトであり、Nx Plugin for AWS の同等のものは ts#infra ジェネレーターです。

Projen プロジェクトと同様に、PDK はこれらのプロジェクトが依存する CDK コンストラクトも提供していました。ショッピングリストアプリケーションをこれらの CDK コンストラクトからも移行し、Nx Plugin for AWS によって生成されるものを使用します。

TypeScript CDK インフラストラクチャプロジェクトの生成

Section titled “TypeScript CDK インフラストラクチャプロジェクトの生成”

ts#infra ジェネレーターを実行して、packages/infra にインフラストラクチャプロジェクトをセットアップします:

Terminal window
pnpm nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive
変更されるファイルを確認するためにドライランを実行することもできます
Terminal window
pnpm nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive --dry-run

CDK インフラストラクチャの移行

Section titled “CDK インフラストラクチャの移行”

PDK ショッピングリストアプリケーションは、CDK アプリケーションスタック内で以下のコンストラクトをインスタンス化していました:

  • ショッピングリストを保存する DynamoDB テーブル用の DatabaseConstruct
  • PDK から直接インポートされた Cognito リソース用の UserIdentity
  • Smithy API をデプロイするための MyApi。これは、生成された TypeScript CDK コンストラクトを型安全な統合で使用し、内部的に PDK の TypeSafeRestApi CDK コンストラクトに依存していました。
  • Website をデプロイするための Website。PDK の StaticWebsite CDK コンストラクトをラップしていました。

次に、これらのそれぞれを新しいプロジェクトに移行します。

アプリケーションスタックのコピー
Section titled “アプリケーションスタックのコピー”

PDK ショッピングリストアプリケーションから packages/infra/src/stacks/application-stack.ts を新しいプロジェクトの全く同じ場所にコピーします。TypeScript エラーが表示されますが、以下で対処します。

データベースコンストラクトのコピー
Section titled “データベースコンストラクトのコピー”

PDK ショッピングリストアプリケーションには、packages/src/constructs/database.tsDatabase コンストラクトがありました。これを新しいプロジェクトの全く同じ場所にコピーします。

Nx Plugin for AWS はセキュリティテストに Checkov を使用しており、PDK Nag よりも少し厳格であるため、いくつかの抑制を追加する必要があります:

constructs/database.ts
import { suppressRules } from '@shopping-list/common-constructs';
...
suppressRules(
this.shoppingListTable,
['CKV_AWS_28', 'CKV_AWS_119'],
'Backup and KMS key not required for this project',
);

application-stack.ts で、DatabaseConstruct のインポートを ESM 構文を使用するように更新します:

stacks/application-stack.ts
import { DatabaseConstruct } from '../constructs/database';
import { DatabaseConstruct } from '../constructs/database.js';
UserIdentity コンストラクトの移行
Section titled “UserIdentity コンストラクトの移行”

UserIdentity コンストラクトは、一般的にインポートを調整することで変更なしで置き換えることができます。

import { UserIdentity } from "@aws/pdk/identity";
import { UserIdentity } from '@shopping-list/common-constructs';
...
const userIdentity = new UserIdentity(this, `${id}UserIdentity`);

新しい UserIdentity コンストラクトで使用される基礎となるコンストラクトは aws-cdk-lib から直接提供されることに注意してください。PDK は @aws-cdk/aws-cognito-identitypool-alpha を使用していました。

PDK ショッピングリストアプリケーションには、constructs/apis/myapi.ts にコンストラクトがあり、Smithy モデルから Type Safe API が生成した CDK コンストラクトをインスタンス化していました。

このコンストラクトに加えて、PDK プロジェクトは @handler トレイトを使用していたため、生成された Lambda 関数 CDK コンストラクトも生成されていました。

Type Safe API と同様に、Nx Plugin for AWS は Smithy モデルに基づいて統合の型安全性を提供しますが、はるかにシンプルで柔軟な方法で実現されています。ビルド時に CDK コンストラクト全体を生成する代わりに、最小限の「メタデータ」のみが生成され、packages/common/constructs/src/app/apis/api.ts がそれを汎用的な方法で使用します。コンストラクトの使用方法の詳細については、ts#smithy-api ジェネレーターガイドを参照してください。

以下の手順に従ってください:

  1. application-stack.tsApi コンストラクトをインスタンス化します

    stacks/application-stack.ts
    import { MyApi } from "../constructs/apis/myapi";
    import { Api } from '@shopping-list/common-constructs';
    ...
    const myapi = new MyApi(this, "MyApi", {
    databaseConstruct,
    userIdentity,
    });
    const api = new Api(this, 'MyApi', {
    integrations: Api.defaultIntegrations(this).build(),
    });

    ここで Api.defaultIntegrations(this).build() を使用していることに注目してください - デフォルトの動作は API の各オペレーションに対して Lambda 関数を作成することで、これは myapi.ts で持っていたのと同じ動作です。

  2. Lambda 関数に DynamoDB テーブルへのアクセス権限を付与します。

    PDK ショッピングリストアプリケーションでは、DatabaseConsructMyApi に渡され、生成された各関数コンストラクトに関連する権限を追加していました。Api コンストラクトの型安全な integrations プロパティにアクセスすることで、application-stack.ts ファイル内で直接これを行います:

    stacks/application-stack.ts
    // Grant our lambda functions scoped access to call Dynamo
    databaseConstruct.shoppingListTable.grantReadData(
    api.integrations.getShoppingLists.handler,
    );
    [
    api.integrations.putShoppingList.handler,
    api.integrations.deleteShoppingList.handler,
    ].forEach((f) => databaseConstruct.shoppingListTable.grantWriteData(f));
  3. 認証されたユーザーに API を呼び出す権限を付与します。

    PDK アプリケーションの myapi.ts 内では、認証されたユーザーにも API を呼び出すための IAM 権限が付与されていました。application-stack.ts で同等のことを行います:

    stacks/application-stack.ts
    api.grantInvokeAccess(userIdentity.identityPool.authenticatedRole);

最後に、packages/common/constructs/src/app/static-websites/website.ts から Website コンストラクトを application-stack.ts に追加します。これは PDK ショッピングリストアプリケーションの packages/infra/src/constructs/websites/website.ts と同等です。

import { Website } from "../constructs/websites/website";
import { Website } from '@shopping-list/common-constructs';
...
new Website(this, "Website", {
userIdentity,
myapi,
});
new Website(this, 'Website');

ID や API を Website に渡していないことに注意してください - ランタイム設定は Nx Plugin for AWS によって提供される各コンストラクト内で管理され、UserIdentityApi が必要な値を登録し、Website が静的ウェブサイトの /runtime-config.json へのデプロイを管理します。

コードベースの関連部分をすべて新しいプロジェクトに移行したので、プロジェクトをビルドしましょう。

Terminal window
pnpm nx run-many --target build

完全に移行されたコードベースが完成したので、デプロイについて見ていきましょう。この時点で2つの方法があります。

すべて新規リソース(シンプル)

Section titled “すべて新規リソース(シンプル)”

最もシンプルなアプローチは、これを完全に新しいアプリケーションとして扱うことです。つまり、新しいDynamoDBテーブルとCognito User Poolで「最初からやり直す」ことになり、すべてのユーザーとそのショッピングリストが失われます。このアプローチでは、単純に以下を実行します:

  1. shopping_listという名前のDynamoDBテーブルを削除します

  2. 新しいアプリケーションをデプロイします:

    Terminal window
    pnpm nx deploy infra shopping-list-infra-sandbox/*

🎉 これで完了です! 🎉

ダウンタイムなしで既存のステートフルリソースを移行(より複雑)

Section titled “ダウンタイムなしで既存のステートフルリソースを移行(より複雑)”

実際には、顧客のダウンタイムを避けながら、既存のAWSリソースを新しいコードベースで管理できるように移行したい場合が多いでしょう。

ショッピングリストアプリケーションの場合、重要なステートフルリソースは、ユーザーのショッピングリストを含むDynamoDBテーブルと、登録されたすべてのユーザーの詳細を含むUser Poolです。大まかな計画としては、これら2つの重要なリソースを保持し、新しいスタックで管理されるように移動してから、DNSを更新して新しいウェブサイト(および顧客に公開されている場合はAPI)を指すようにします。

  1. 保持したい既存のリソースを参照するように新しいアプリケーションを更新します。

    ショッピングリストアプリケーションでは、DynamoDBテーブルに対してこれを行います

    constructs/database.ts
    this.shoppingListTable = new Table(this, 'ShoppingList', {
    ...
    this.shoppingListTable = Table.fromTableName(
    this,
    'ShoppingList',
    'shopping_list',
    );

    そしてCognito User Poolに対して

    packages/common/constructs/src/core/user-identity.ts
    this.userPool = this.createUserPool();
    this.userPool = UserPool.fromUserPoolId(
    this,
    'UserPool',
    '<your-user-pool-id>',
    );
  2. 新しいアプリケーションをビルドしてデプロイします:

    Terminal window
    pnpm nx run-many --target build
    Terminal window
    pnpm nx deploy infra shopping-list-infra-sandbox/*

    これで、既存のリソースを参照する新しいアプリケーションが立ち上がりましたが、まだトラフィックは受け取っていません。

  3. 新しいアプリケーションが期待通りに動作することを確認するために、完全な統合テストを実行します。ショッピングリストアプリケーションの場合、ウェブサイトをロードして、サインインしてショッピングリストの作成、表示、編集、削除ができることを確認します。

  4. 新しいアプリケーションで既存のリソースを参照する変更を元に戻しますが、まだデプロイはしません。

    constructs/database.ts
    this.shoppingListTable = new Table(this, 'ShoppingList', {
    ...
    this.shoppingListTable = Table.fromTableName(
    this,
    'ShoppingList',
    'shopping_list',
    );

    そしてCognito User Poolに対して

    packages/common/constructs/src/core/user-identity.ts
    this.userPool = this.createUserPool();
    this.userPool = UserPool.fromUserPoolId(
    this,
    'UserPool',
    '<your-user-pool-id>',
    );

    そしてビルドを実行します

    Terminal window
    pnpm nx run-many --target build
  5. 新しいアプリケーションのpackages/infraフォルダでcdk importを使用して、インポートするように促されるリソースを確認します。

    New Application
    cd packages/infra
    pnpm exec cdk import shopping-list-infra-sandbox/Application --force

    Enterキーを押してプロンプトを進めます。リソースが別のスタックによって管理されているため、インポートは失敗します - これは予想通りです。このステップは、保持する必要があるリソースを確認するためだけに行いました。次のような出力が表示されます:

    Terminal window
    shopping-list-infra-sandbox/Application/ApplicationUserIdentity/UserPool/smsRole/Resource (AWS::IAM::Role): enter RoleName (empty to skip)
    shopping-list-infra-sandbox/Application/ApplicationUserIdentity/UserPool/Resource (AWS::Cognito::UserPool): enter UserPoolId (empty to skip)
    shopping-list-infra-sandbox/Application/Database/ShoppingList/Resource (AWS::DynamoDB::Table): import with TableName=shopping_list (y/n) y

    これにより、実際には新しいスタックにインポートする必要があるリソースが3つあることがわかります。

  6. 前のステップで発見されたリソースに対してRemovalPolicyRETAINに設定するように、古いPDKプロジェクトを更新します。この記事を書いている時点では、User PoolとDynamoDBテーブルの両方でこれがデフォルトですが、上記で発見したSMS Roleについては更新する必要があります:

    application-stack.ts
    const userIdentity = new UserIdentity(this, `${id}UserIdentity`, {
    userPool,
    });
    const smsRole = userIdentity.userPool.node.findAll().filter(
    c => CfnResource.isCfnResource(c) &&
    c.node.path.includes('/smsRole/'))[0] as CfnResource;
    smsRole.applyRemovalPolicy(RemovalPolicy.RETAIN);
  7. 削除ポリシーが適用されるようにPDKプロジェクトをデプロイします

    PDK Application
    cd packages/infra
    npx projen deploy
  8. CloudFormationコンソールを確認し、上記のcdk importステップで促された値を記録します

    1. User Pool ID、例:us-west-2_XXXXX
    2. SMS Role Name、例:infra-sandbox-UserIdentityUserPoolsmsRoleXXXXXX
  9. リソースを作成する代わりに既存のリソースを参照するようにPDKプロジェクトを更新します

    constructs/database.ts
    this.shoppingListTable = new Table(this, 'ShoppingList', {
    ...
    this.shoppingListTable = Table.fromTableName(
    this,
    'ShoppingList',
    'shopping_list',
    );

    そしてCognito User Poolに対して

    application-stack.ts
    const userPool = UserPool.fromUserPoolId(
    this,
    'UserPool',
    '<your-user-pool-id>',
    );
    const userIdentity = new UserIdentity(this, `${id}UserIdentity`, {
    // PDK construct accepts UserPool not IUserPool, but this still works!
    userPool: userPool as any,
    });
  10. PDKプロジェクトを再度デプロイします。これにより、リソースはPDKプロジェクトのCloudFormationスタックによって管理されなくなります。

    PDK Application
    cd packages/infra
    npx projen deploy
  11. リソースが管理されていない状態になったので、新しいアプリケーションでcdk importを実行して実際にインポートを実行できます:

    New Application
    cd packages/infra
    pnpm exec cdk import shopping-list-infra-sandbox/Application --force

    プロンプトが表示されたら値を入力すると、インポートが正常に完了するはずです。

  12. 新しいアプリケーションを再度デプロイして、これらの既存のリソース(現在は新しいスタックによって管理されています)への変更が確実に行われるようにします:

    Terminal window
    pnpm nx deploy infra shopping-list-infra-sandbox/*
  13. 新しいアプリケーションの完全なテストを再度実行します

  14. DNSレコードを更新して、新しいウェブサイト(および必要に応じてAPI)を指すようにします。

    Route53の重み付けルーティングを使用した段階的なアプローチを推奨します。これにより、最初はリクエストの一部が新しいアプリケーションに送られます。メトリクスを監視しながら、古いPDKアプリケーションにトラフィックが送られなくなるまで、新しいアプリケーションの重みを増やすことができます。

    DNSがなく、ウェブサイトとAPIに自動生成されたドメインを使用している場合は、リクエストをプロキシすることを検討できます(例:CloudFront HTTPオリジンまたはAPI Gateway HTTP統合経由)。

  15. PDKアプリケーションのメトリクスを監視してトラフィックがないことを確認し、最後に古いCloudFormationスタックを破棄します:

    Terminal window
    cd packages/infra
    npx projen destroy

これはかなり複雑でしたが、ユーザーをシームレスに新しいアプリケーションに移行することに成功しました! 🎉🎉🎉

これで、PDKに対するNx Plugin for AWSの新しい利点が得られました:

  • より高速なビルド
  • ローカルAPI開発サポート
  • バイブコーディングに適したコードベース(MCPサーバーをお試しください!
  • より直感的な型安全なクライアント/サーバーコード
  • その他多数!

このセクションでは、上記の移行例でカバーされていないPDKの機能に関するガイダンスを提供します。

PDKから移行する際の一般的なルールとして、PDK Monorepoとの類似性を考慮して、Nx Workspaceでプロジェクトを開始することをお勧めします。また、新しいタイプを構築する際の基本要素として、当社のジェネレーターを使用することをお勧めします。

Terminal window
pnpm create @aws/nx-workspace my-project

CDK Graph は、接続された CDK リソースのグラフを構築し、2つのプラグインを提供していました:

CDK Graph Diagram Plugin は、CDK インフラストラクチャから AWS アーキテクチャ図を生成します。

同様の決定論的アプローチとして、CDK-Dia が実行可能な代替手段です。

生成 AI の進歩により、多くの基盤モデルが CDK インフラストラクチャから高品質な図を作成できるようになりました。AWS Diagram MCP Server を試してみることをお勧めします。ウォークスルーについては、このブログ記事をご覧ください。

CDK Graph Threat Composer Plugin は、CDK コードから Threat Composer の脅威モデルのスターターを生成します。

このプラグインは、脅威の例を含むベース脅威モデルを単純にフィルタリングし、スタックが使用するリソースに基づいてそれらをフィルタリングすることで機能していました。

これらの特定の脅威の例に興味がある場合は、ベース脅威モデルをコピーしてフィルタリングするか、基盤モデルが同様のものを生成するのを助けるコンテキストとして使用できます。

AWS Arch は、CloudFormation リソースとそれに関連するアーキテクチャアイコンの間のマッピングを CDK Graph 上で提供していました。

アイコン関連のリソースについては、AWS Architecture Icons ページを参照してください。Diagrams も、コードとして図を構築する方法を提供しています。

これを直接使用していた場合は、プロジェクトをフォークして所有権を取得することを検討してください!

PDKはPDKPipelineProjectを提供しており、これはCDKインフラストラクチャプロジェクトをセットアップし、いくつかのCDK PipelinesリソースをラップしたCDKコンストラクトを使用していました。

これから移行するには、CDK Pipelinesコンストラクトを直接使用できます。しかし実際には、GitHub actionsやGitLab CI/CDのようなものを使用する方がより簡単です。そこではCDK Stagesを定義し、適切なステージに対してデプロイコマンドを直接実行します。

PDK NagCDK Nag をラップし、プロトタイプ構築に特化したルールセットを提供します。

PDK Nag から移行するには、CDK Nag を直接使用してください。同じルールセットが必要な場合は、こちらのドキュメントに従って独自の「パック」を作成できます。

Type Safe API で最もよく使用されるコンポーネントは上記の移行例でカバーされていますが、他にも機能があり、その移行の詳細は以下の通りです。

Nx Plugin for AWS は Smithy でモデル化された API をサポートしていますが、OpenAPI で直接モデル化された API はサポートしていません。ts#smithy-api ジェネレーターは良い出発点であり、その後変更することができます。model プロジェクトの src フォルダーに Smithy の代わりに OpenAPI 仕様を定義し、build.Dockerfile を変更して、NPM で利用できない場合は、クライアント/サーバー用の希望するコード生成ツールを使用できます。希望するツールが NPM にある場合は、Nx ワークスペースに開発依存関係としてインストールし、Nx ビルドターゲットとして直接呼び出すことができます。

OpenAPI でモデル化された型安全なバックエンドについては、OpenAPI Generator Server Generators のいずれかの使用を検討できます。これらは AWS Lambda 用に直接生成されませんが、AWS Lambda Web Adapter を使用して、多くのギャップを埋めることができます。

TypeScript クライアントの場合、ts#website ジェネレーターconnection ジェネレーターを、サンプルの ts#apiframeworksmithy に設定)と共に使用して、クライアントがどのように生成され、ウェブサイトと統合されるかを確認できます。これにより、open-api#ts-client または open-api#ts-hooks ジェネレーターを呼び出してクライアントを生成するビルドターゲットが構成されます。これらのジェネレーターを OpenAPI 仕様に向けることで、自分で使用できます。

他の言語については、OpenAPI Generator のジェネレーターのいずれかがニーズに合うかどうかも確認できます。

また、ts#nx-generator ジェネレーターを使用して、カスタムジェネレーターを構築することもできます。OpenAPI からコードを生成する方法の詳細については、そのジェネレーターのドキュメントを参照してください。Nx Plugin for AWS のテンプレートを出発点として使用できます。さらにインスピレーションを得るために、PDK コードベースのテンプレートを参照することもできますが、テンプレートが操作するデータ構造は Nx Plugin for AWS とは少し異なることに注意してください。

TypeSpec の場合、上記の OpenAPI のセクションも適用されます。ts#smithy-api を生成することから始め、TypeSpec コンパイラと OpenAPI パッケージを Nx ワークスペースにインストールし、model プロジェクトの compile ターゲットを更新して代わりに tsp compile を実行し、dist ディレクトリに OpenAPI 仕様を出力するようにします。

推奨されるアプローチは、TypeSpec HTTP Server generator for JavaScript を使用してサーバーコードを生成することです。これは TypeSpec モデルで直接動作するためです。

AWS Lambda でサーバーを実行するには、AWS Lambda Web Adapter を使用できます。

上記の OpenAPI オプションのいずれかを使用することもできます。

TypeSpec には、Type Safe API がサポートする 3 つの言語すべてのクライアント用の独自のコードジェネレーターがあります:

TypeSpec は OpenAPI にコンパイルできるため、上記の OpenAPI セクションも適用されます。

上記の移行例では、ts#smithy-api ジェネレーターを使用するための移行について概説しています。このセクションでは、Python と Java のバックエンドとクライアントのオプションについて説明します。

Smithy code generator for Java。これには Java サーバージェネレーターと、生成された Java サーバーを AWS Lambda で実行するためのアダプターがあります。

Smithy には Python 用のサーバージェネレーターがないため、OpenAPI 経由で行う必要があります。潜在的なオプションについては、OpenAPI でモデル化された API に関する上記のセクションを参照してください。

Smithy code generator for Java。これには Java クライアントジェネレーターがあります。

Python クライアントについては、Smithy Python をチェックしてください。

TypeScript については、Smithy TypeScript をチェックするか、ts#smithy-api で採用したのと同じアプローチで OpenAPI 経由で行います(tRPC、FastAPI、Smithy API 間で TanStack Query フックを介して一貫性を持たせるため、このオプションを選択しました)。

Type Safe API は、複数の Smithy ベースの API で再利用できる Smithy モデルを含むプロジェクトを構成する SmithyShapeLibraryProject という名前の Projen プロジェクトタイプを提供していました。

同等のものは、typeshapes に設定した smithy#project ジェネレーターです:

Terminal window
pnpm nx g @aws/nx-plugin:smithy#project --name=my-shapes --type=shapes
変更されるファイルを確認するためにドライランを実行することもできます
Terminal window
pnpm nx g @aws/nx-plugin:smithy#project --name=my-shapes --type=shapes --dry-run

SmithyShapeLibraryProject からシェイプを生成されたプロジェクトの src フォルダーに移動し、ライブラリを API のモデルの依存関係として接続する方法については、Smithy プロジェクトガイドを参照してください。

Type Safe API は、以下のデフォルトインターセプターを提供していました:

  • Powertools for AWS Lambda を使用したロギング、トレーシング、メトリクスインターセプター
  • キャッチされない例外を処理するための try-catch インターセプター
  • CORS ヘッダーを返すための CORS インターセプター

ts#smithy-api ジェネレーターは、Middy を使用して Powertools for AWS Lambda でロギング、トレーシング、メトリクスを計装します。try-catch インターセプターの動作は Smithy TypeScript SSDK に組み込まれており、CORS ヘッダーは handler.ts に追加されます。

任意の言語でのロギング、トレーシング、メトリクスインターセプターについては、Powertools for AWS Lambda を直接使用してください。

カスタムインターセプターの移行には、以下のライブラリの使用をお勧めします:

Type Safe API は Redocly CLI を使用したドキュメント生成を提供していました。これは、上記のように移行した既存のプロジェクトに非常に簡単に追加できます。

  1. Redocly CLI をインストールします

    Terminal window
    pnpm add -Dw @redocly/cli
  2. redocly build-docs を使用して、model プロジェクトにドキュメント生成ターゲットを追加します。例:

    model/project.json
    {
    ...
    "documentation": {
    "cache": true,
    "outputs": ["{workspaceRoot}/dist/{projectRoot}/documentation"],
    "executor": "nx:run-commands",
    "options": {
    "command": "redocly build-docs dist/packages/api/model/build/openapi/openapi.json --output=dist/packages/api/model/documentation/index.html",
    "cwd": "{workspaceRoot}"
    },
    "dependsOn": ["compile"]
    }
    }

OpenAPI Generator documentation generators を検討することもできます。

Type Safe API は、生成されたインフラストラクチャパッケージ内でモックを生成していました。

JSON スキーマに基づいてモックデータを作成できる JSON Schema Faker に移行できます。これは OpenAPI 仕様で直接動作し、model プロジェクトビルドの一部として実行できる CLI があります。

CDK インフラストラクチャを更新して、JSON Schema Faker によって出力された JSON ファイルを読み取り、生成された metadata.gen.tsts#smithy-api ジェネレーターを使用したと仮定)に基づいて、統合に適切な API Gateway MockIntegration を返すことができます。

Type Safe API は、バックエンドで異なる言語の混合で API を実装することをサポートしていました。これは、CDK で API コンストラクトをインスタンス化する際に統合に「オーバーライド」を提供することでも実現できます:

application-stack.ts
const pythonLambdaHandler = new Function(this, 'PythonImplementation', {
runtime: Runtime.PYTHON_3_12,
...
});
new MyApi(this, 'MyApi', {
integrations: Api.defaultIntegrations(this)
.withOverrides({
echo: {
integration: new LambdaIntegration(pythonLambdaHandler),
handler: pythonLambdaHandler,
},
})
.build(),
});

ts#smithy-api と TypeScript Server SDK を使用している場合、サービスをコンパイルするためにサービス/ルーターを「スタブ」する必要があります。例:

service.ts
export const Service: ApiService<ServiceContext> = {
...
Echo: () => { throw new Error(`Not Implemented`); },
};

Type Safe API は、SpecRestApi コンストラクトを内部で使用していたため、OpenAPI 仕様に基づいてリクエストボディのネイティブ API Gateway 検証を追加していました。

ts#smithy-api ジェネレーターでは、検証は Server SDK 自体によって実行されます。これはほとんどのサーバージェネレーターで同じです。

ネイティブ API Gateway 検証を実装したい場合は、packages/common/constructs/src/core/api/rest-api.ts を変更して、OpenAPI 仕様から各操作のリクエストボディの関連する JSON スキーマを読み取ることで実装できます。

残念ながら、API Gateway と Lambda を使用した Type Safe API の websocket API のモデル駆動型 API 開発への簡単な移行パスはありません。ただし、ガイドのこのセクションでは、少なくともいくつかのアイデアを提供することを目的としています。

OpenAPI や TypeSpec の代わりに AsyncAPI を使用して API をモデル化することを検討してください。これは非同期 API を処理するように設計されているためです。AsyncAPI NodeJS Template は、たとえば ECS でホストできる Node websocket バックエンドを生成できます。

インフラストラクチャには AppSync Events を検討し、Powertools を使用することもできます。このブログ投稿は一読の価値があります!

別のオプションは、AppSync で websocket を使用した GraphQL API を使用することです。これについては GitHub issue があり、+1 できます!詳細とサンプルプロジェクトへのリンクについては、AppSync developer guide を参照してください。

Type Safe API と同じベンダー拡張を解釈する独自のコードジェネレーターを構築することも検討できます。カスタム OpenAPI ベースのコードジェネレーターの構築に関する詳細については、OpenAPI でモデル化された API セクションを参照してください。Type Safe API が API Gateway Websocket API Lambda ハンドラーに使用するテンプレートはこちら、クライアントはこちらにあります。

tRPC を使用するために ts#trpc-api ジェネレーターへの移行を検討することもできます。執筆時点では、サブスクリプション/ストリーミングのサポートはまだありませんが、これが必要な場合は、これを追跡している GitHub issue に +1 を追加してください。

Smithy はプロトコルに依存しませんが、Websocket プロトコルのサポートはまだありません。サポートを追跡しているこの GitHub issueを参照してください。

PythonまたはJavaでのインフラストラクチャ

Section titled “PythonまたはJavaでのインフラストラクチャ”

PDK は Python と Java で書かれた CDK インフラストラクチャをサポートしていました。現時点では、Nx Plugin for AWS ではこれをサポートしていません。

推奨される進め方は、CDK インフラストラクチャを TypeScript に移行するか、または当社のジェネレーターを使用して共通コンストラクトパッケージを希望する言語に移行することです。このような移行を加速するために、生成 AI を使用できます。例えば Kiro CLI などです。合成された CloudFormation テンプレートが同一になるまで、AI エージェントに移行を繰り返させることができます。

Type Safe API の Python または Java で生成されたインフラストラクチャについても同様です。共通コンストラクトパッケージから汎用的な rest-api.ts コンストラクトを翻訳し、ターゲット言語用の独自のシンプルなメタデータジェネレーターを実装できます(OpenAPI でモデル化された API セクションを参照してください)。

CDK コードを追加するための基本的な Python プロジェクトには、py#project ジェネレーターを使用できます(cdk.json ファイルを移動し、関連するターゲットを追加します)。Java プロジェクトには Nx の @nx/gradle プラグインを使用するか、Maven の場合は @jnxplus/nx-maven を使用できます。

PDKはProjenの上に構築されました。ProjenとNx Generatorsには根本的な違いがあり、技術的には組み合わせることは可能ですが、アンチパターンになる可能性があります。Projenはプロジェクトファイルをコードとして管理するため、直接変更することはできませんが、Nx generatorsはプロジェクトファイルを一度生成した後、コードを自由に変更できます。

Projenを引き続き使用したい場合は、必要なProjenプロジェクトタイプを自分で実装できます。Nx Plugin for AWSのパターンに従うには、当社のgeneratorsを実行するか、GitHubでそのソースコードを調べて、必要なプロジェクトタイプがどのように構築されているかを確認し、Projenのプリミティブを使用して関連部分を実装できます。

Nx Plugin for AWS MCP Serverの紹介

急速に進化するソフトウェア開発の環境において、AIアシスタントは私たちのコーディングの旅における貴重な協力者となっています。多くの開発者は、私たちが親しみを込めて「バイブコーディング」と呼ぶものを受け入れています。これは、人間の創造性とAIの支援との協調的なダンスです。新たに登場した実践と同様に、エキサイティングな利点と注目すべき課題の両方が伴います。この投稿では、AWSの製品とサービスを使用する際のAI支援開発体験を強化する Nx Plugin for AWS MCP Server を紹介します。

バイブコーディング、つまりAIアシスタントと協力してソフトウェアを構築する実践は、多くの組織がソフトウェア開発にアプローチする方法を変革しました。構築したいものを説明すると、AIアシスタントがコードとテストの記述、ビルドコマンドの実行、そして大小のタスクを完了するための協調的な反復を通じて、あなたのビジョンを実現するのを支援します。

この協調的なアプローチは開発サイクルを大幅に加速しました。以前は手動で記述するのに数時間かかっていた複雑な実装が、多くの場合数分で完了できるようになりました。

その利点にもかかわらず、バイブコーディングにはフローを妨げ、フラストレーションにつながる落とし穴があります。AIツールはプロジェクト全体で一貫性のないパターンを生成する可能性があり、これは後々メンテナンスの頭痛の種となる可能性があります。具体的なガイダンスがなければ、AIは経験豊富な開発者が自然に組み込むであろう重要なAWS固有のベストプラクティスやセキュリティの考慮事項を見逃す可能性があります。

明確なプロジェクト構造がなければ、AI支援コードは整理されず、メンテナンスが困難になる可能性があります。AIは、すでに確立されたソリューションがある問題に対してカスタム実装を作成し、不必要に車輪の再発明をする可能性があります。

これらの課題は、特に単一のフレームワークの範囲内だけでなく、相互接続するさまざまなAWSサービスを扱う場合に、技術的負債、セキュリティの脆弱性、フラストレーションにつながる可能性があります。

Nx Plugin for AWS は、Nxモノレポツールを使用してAWSアプリケーションを構築するための構造化された基盤を提供します。白紙のキャンバスから始める代わりに、プラグインはプロジェクト組織のための一貫したフレームワークを提供します。

プラグインは、一般的なプロジェクトタイプのジェネレーターを通じて一貫したプロジェクトスキャフォールディングを保証し、コードベース全体の構造的整合性を維持します。AWSのベストプラクティスに従う事前設定されたテンプレートを組み込み、開発者が一般的な落とし穴やセキュリティの問題を回避するのに役立ちます。統合されたツールは、AWSアプリケーションのビルド、テスト、デプロイのための組み込みコマンドを提供し、ローカル開発サーバーを通じて開発ワークフローを合理化します。さらに、複雑なプロジェクトのためのNxの強力な依存関係管理を活用し、モノレポ管理を簡素化します。

この構造を提供することで、Nx Plugin for AWS はAIアシスタントに作業するための明確な構造を与えます。パターンをゼロから発明するのではなく、AIアシスタントは確立された規約に従うことができ、より一貫性があり保守可能なコードベースにつながります。

Model Context Protocol (MCP) は、AIアシスタントが外部ツールやリソースと対話できるようにするオープンスタンダードです。Nx Plugin for AWS MCP server は、Nx Plugin for AWS に関する専門知識でAIアシスタントの機能を拡張します。

MCP server は、AWS開発に特化したベストプラクティス、利用可能なプロジェクト構造、実装パターンに関するコンテキスト情報を提供します。AIツールがワークスペースを作成し、ジェネレーターを実行して一般的なプロジェクトタイプをスキャフォールドできるようにします。このコンテキスト認識により、AIは確立されたパターンに沿った、一般的な落とし穴を回避する、より情報に基づいた提案を行うことができます。

ベストプラクティスに沿わない、または存在しない機能を参照する可能性のあるコードを生成する代わりに、AIアシスタントはMCP server を活用してプロジェクトの基盤を築くことができます。その結果、プロジェクトのコアコンポーネントのための堅固な基盤から始め、AIを使用してビジネスロジックを埋めることができる、より決定論的で信頼性の高い開発体験が得られます。

より構造化され信頼性の高いAI支援AWS開発を探求することに興味がある場合は、Nx Plugin for AWS MCP Server を試してみてください。お気に入りのAIアシスタント(Kiro、Kiro CLI、Cline、Claude Codeなど)で、次のMCP Server設定を使用してセットアップできます:

{
"mcpServers": {
"nx-plugin-for-aws": {
"command": "npx",
"args": ["-y", "@aws/nx-plugin-mcp"]
}
}
}

詳細な手順については、Building with AIガイドを参照してください。

@aws/nx-plugin へようこそ

ついにリリースです!🚀

Nx Plugin for AWS は、AWS 上でフルスタックアプリケーションを構築およびデプロイするプロセスを簡素化するためのツールキットを提供する Nx プラグインです。開発者にアプリケーションコードと IaC コードの両方について事前設定されたテンプレートを提供し、セットアップと設定に費やす時間を大幅に削減します。このプラグインは、カスタマイズの柔軟性を維持しながら、AWS サービス統合の複雑さを処理します。

ユーザーは利用可能なジェネレーターのリストから必要なコンポーネントを選択し、設定オプションを提供するだけで、@aws/nx-plugin が必要なスターターコードを生成します。このツールキット内には、API、ウェブサイト、インフラストラクチャを作成できるいくつかのジェネレーターが存在し、さらに型安全なクライアントを使用してフロントエンドをバックエンドに統合する(AST 変換による既存ファイルの更新を含む!)などのより高度な処理も実行できます。

generator

詳細については、プラグインの主要コンポーネントをすべてカバーし、使用方法の良い感触を得られる Dungeon Adventure チュートリアルから始めてください。

皆様のフィードバックをお待ちしております。ご意見や次に見たい機能について、ディスカッションを投稿したり、issue を作成したりすることをお気軽にどうぞ!

試してみる!