Skip to content

ジェネレーターの貢献

@aws/nx-plugin に貢献する新しいジェネレーターを作成しましょう。目標は、tRPC API の新しいプロシージャを生成することです。

まず、プラグインをクローンしましょう:

Terminal window
git clone git@github.com:awslabs/nx-plugin-for-aws.git

次に、インストールとビルドを行います:

Terminal window
cd nx-plugin-for-aws
pnpm i
pnpm nx run-many --target build --all

packages/nx-plugin/src/trpc/procedure に新しいジェネレーターを作成しましょう。

新しいジェネレーターを作成するためのジェネレーターを提供しているので、新しいジェネレーターを素早くスキャフォールドできます!このジェネレーターは次のように実行できます:

Terminal window
pnpm nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API
変更されるファイルを確認するためにドライランを実行することもできます
Terminal window
pnpm nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API --dry-run

次のファイルが生成されたことがわかります:

  • Directorypackages/nx-plugin/src/trpc/procedure
    • schema.json ジェネレーターの入力を定義
    • schema.d.ts スキーマに一致する TypeScript インターフェース
    • generator.ts Nx がジェネレーターとして実行する関数
    • generator.spec.ts ジェネレーターのテスト
  • Directorydocs/src/content/docs/guides/
    • trpc-procedure.mdx ジェネレーターのドキュメント
  • packages/nx-plugin/generators.json ジェネレーターを含むように更新

ジェネレーターに必要なプロパティを追加するためにスキーマを更新しましょう:

{
"$schema": "https://json-schema.org/schema",
"$id": "tRPCProcedure",
"title": "Adds a procedure to a tRPC API",
"type": "object",
"properties": {
"project": {
"type": "string",
"description": "tRPC API project",
"x-prompt": "Select the tRPC API project to add the procedure to",
"x-dropdown": "projects",
"x-priority": "important"
},
"procedure": {
"description": "The name of the new procedure",
"type": "string",
"x-prompt": "What would you like to call your new procedure?",
"x-priority": "important",
},
"type": {
"description": "The type of procedure to generate",
"type": "string",
"x-prompt": "What type of procedure would you like to generate?",
"x-priority": "important",
"default": "query",
"enum": ["query", "mutation"]
}
},
"required": ["project", "procedure"]
}

ジェネレーターは既に packages/nx-plugin/generators.json に接続されていることがわかります:

...
"generators": {
...
"ts#trpc-api#procedure": {
"factory": "./src/trpc/procedure/generator",
"schema": "./src/trpc/procedure/schema.json",
"description": "Adds a procedure to a tRPC API"
}
},
...

tRPC API にプロシージャを追加するには、2つのことを行う必要があります:

  1. 新しいプロシージャ用の TypeScript ファイルを作成
  2. ルーターにプロシージャを追加

新しいプロシージャ用の TypeScript ファイルを作成するために、generateFiles というユーティリティを使用します。これを使用すると、ユーザーが選択したオプションに基づいて変数を使ってジェネレーター内でレンダリングできる EJS テンプレートを定義できます。

まず、packages/nx-plugin/src/trpc/procedure/files/procedures/__procedureNameKebabCase__.ts.template にテンプレートを定義します:

files/procedures/__procedureNameKebabCase__.ts.template
import { publicProcedure } from '../init.js';
import { z } from 'zod';
export const <%- procedureNameCamelCase %> = publicProcedure
.input(z.object({
// TODO: define input
}))
.output(z.object({
// TODO: define output
}))
.<%- procedureType %>(async ({ input, ctx }) => {
// TODO: implement!
return {};
});

テンプレートでは、3つの変数を参照しました:

  • procedureNameCamelCase
  • procedureNameKebabCase
  • procedureType

したがって、これらを generateFiles に渡す必要があります。また、ファイルを生成するディレクトリ、つまりユーザーがジェネレーターの入力として選択した tRPC プロジェクトのソースファイルの場所(つまり sourceRoot)も渡す必要があります。これはプロジェクト構成から抽出できます。

ジェネレーターを更新してそれを行いましょう:

procedure/generator.ts
import {
generateFiles,
joinPathFragments,
readProjectConfiguration,
type Tree,
} from '@nx/devkit';
import type { TrpcProcedureSchema } from './schema.js';
import { formatFilesInSubtree } from '../../utils/format';
import camelCase from 'lodash.camelcase';
import kebabCase from 'lodash.kebabcase';
export const trpcProcedureGenerator = async (
tree: Tree,
options: TrpcProcedureSchema,
) => {
const projectConfig = readProjectConfiguration(tree, options.project);
const procedureNameCamelCase = camelCase(options.procedure);
const procedureNameKebabCase = kebabCase(options.procedure);
generateFiles(
tree,
joinPathFragments(import.meta.dirname, 'files'),
projectConfig.sourceRoot,
{
procedureNameCamelCase,
procedureNameKebabCase,
procedureType: options.type,
},
);
await formatFilesInSubtree(tree);
};
export default trpcProcedureGenerator;

ルーターへのプロシージャの追加

Section titled “ルーターへのプロシージャの追加”

次に、ジェネレーターが新しいプロシージャをルーターに接続するようにします。これは、ユーザーのソースコードを読み取って更新することを意味します!

GritQL を使用して、ソースコードを宣言的に検索および変換します。addDestructuredImport ヘルパーは名前付きインポートを追加し、applyGritQL は GritQL パターンを適用してルーターのオブジェクトリテラルにプロシージャを追加します。

procedure/generator.ts
import {
generateFiles,
joinPathFragments,
readProjectConfiguration,
type Tree,
} from '@nx/devkit';
import type { TrpcProcedureSchema } from './schema.js';
import { formatFilesInSubtree } from '../../utils/format';
import camelCase from 'lodash.camelcase';
import kebabCase from 'lodash.kebabcase';
import { addDestructuredImport, applyGritQL } from '../../utils/ast';
export const trpcProcedureGenerator = async (
tree: Tree,
options: TrpcProcedureSchema,
) => {
const projectConfig = readProjectConfiguration(tree, options.project);
const procedureNameCamelCase = camelCase(options.procedure);
const procedureNameKebabCase = kebabCase(options.procedure);
generateFiles(
tree,
joinPathFragments(import.meta.dirname, 'files'),
projectConfig.sourceRoot,
{
procedureNameCamelCase,
procedureNameKebabCase,
procedureType: options.type,
},
);
const routerPath = joinPathFragments(projectConfig.sourceRoot, 'router.ts');
await addDestructuredImport(
tree,
routerPath,
[procedureNameCamelCase],
`./procedures/${procedureNameKebabCase}.js`,
);
await applyGritQL(
tree,
routerPath,
`\`router({ $props })\` => \`router({ $props, ${procedureNameCamelCase} })\` where { $props <: not contains \`${procedureNameCamelCase}\` }`,
);
await formatFilesInSubtree(tree);
};
export default trpcProcedureGenerator;

ジェネレーターを実装したので、ダンジョンアドベンチャープロジェクトでテストできるようにコンパイルしましょう。

Terminal window
pnpm nx compile @aws/nx-plugin

ジェネレーターをテストするために、ローカルの Nx Plugin for AWS を既存のコードベースにリンクします。

tRPC API を持つテストプロジェクトの作成

Section titled “tRPC API を持つテストプロジェクトの作成”

別のディレクトリに、新しいテストワークスペースを作成します:

Terminal window
pnpm create @aws/nx-workspace trpc-generator-test

次に、プロシージャを追加する tRPC API を生成しましょう:

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

ローカルの Nx Plugin for AWS をリンク

Section titled “ローカルの Nx Plugin for AWS をリンク”

コードベースで、ローカルの @aws/nx-plugin をリンクしましょう:

Terminal window
cd path/to/trpc-generator-test
pnpm link path/to/nx-plugin-for-aws/dist/packages/nx-plugin

新しいジェネレーターを試してみましょう:

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

成功すれば、新しいプロシージャが生成され、router.ts のルーターにプロシージャが追加されているはずです。

ここまで到達し、まだ Nx ジェネレーターを試す時間がある場合は、プロシージャジェネレーターに追加する機能の提案をいくつか示します:

次のようにして、ネストされたルーターをサポートするようにジェネレーターを更新してみてください:

  • procedure 入力にドット表記を受け入れる(例:games.query
  • 逆ドット表記に基づいた名前でプロシージャを生成する(例:queryGames
  • 適切なネストされたルーターを追加する(または既に存在する場合は更新する!)

ジェネレーターは、tRPC API ではない project をユーザーが選択するなど、潜在的な問題から保護する必要があります。この例については、connection ジェネレーターを参照してください。

ジェネレーターのユニットテストを書きましょう。これらは実装が非常に簡単で、ほとんどが次の一般的な流れに従います:

  1. createTreeUsingTsSolutionSetup() を使用して空のワークスペースツリーを作成
  2. ツリーに既に存在すべきファイルを追加(例:tRPC バックエンドの project.jsonsrc/router.ts
  3. テスト対象のジェネレーターを実行
  4. ツリーに期待される変更が行われたことを検証

新しいワークスペースでジェネレーターを実行し、すべてがビルドされることを確認する「スモークテスト」のスイートがあります。最低限、新しいジェネレーターは両方のジェネレーターマトリックスに追加して、スモークテストで実行されるようにする必要があります:

  • e2e/src/smoke-tests/generator-matrix.ts — ユーザーが行うのとまったく同じように、CLI を通じて各ジェネレーターを一度に1つずつ実行します。
  • packages/nx-plugin/src/internal/test-matrix/generator.ts — バージョン間の移行をテストするために他のすべてを構成する隠しジェネレーター。

ジェネレーターマトリックスはジェネレーターを実行してワークスペースをビルドするだけで、インフラストラクチャをインスタンス化しないことに注意してください。インフラストラクチャをデプロイするジェネレーターの場合は、デプロイメント e2e テスト(e2e/src/smoke-tests/cdk-deploy.spec.tsterraform-deploy.spec.ts)を拡張して、実際にリソースをデプロイし(cdk deploy / terraform apply 経由)、deploy-invocations.ts にアサーションを追加して、デプロイされたリソースを呼び出し、期待どおりに動作することを確認することを検討してください。

ジェネレーターがローカル開発サーバーを提供する場合は、ローカル開発 e2e テスト(e2e/src/smoke-tests/local-dev.spec.ts)に追加することを検討してください。これは dev ターゲットを起動し、実行中のサーバーを実行します。

貢献を加速するための一般的なガイダンス

Section titled “貢献を加速するための一般的なガイダンス”

このセクションには、Nx Plugin for AWS での作業時に役立つ一般的なガイダンスが含まれています。

実際のプロジェクトから逆算する

Section titled “実際のプロジェクトから逆算する”

新しいジェネレーターを構築したり、既存のジェネレーターに機能/修正を追加したりする有用な方法は、_最初に実際に構築する_ことです。この方法で、アイデアを検証し、必要な機能を実現するために迅速に反復できます。望ましい結果に落ち着いた後、ジェネレーターを更新できます。

実際には、このプロセスは次のようになります:

  1. 新しいワークスペースを作成

    Terminal window
    pnpm create @aws/nx-workspace my-project
  2. 新しいジェネレーター/機能/修正の前提条件となる可能性のあるジェネレーターを実行

  3. 変更をコミット(git commit

  4. 必要な変更を行い、必要に応じてテスト

  5. 変更の git diff を使用して、Nx Plugin for AWS に加えるべき変更を通知

  6. 最終的なエンドツーエンドテスト(@aws/nx-plugin をリンク)を実行して、ジェネレーターが必要な変更を提供することを確認