콘텐츠로 이동

생성기 기여하기

@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에 생성합니다.

새 제너레이터를 빠르게 스캐폴딩할 수 있도록 제너레이터 생성용 제너레이터를 제공합니다! 다음 명령으로 실행할 수 있습니다:

  1. 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
  2. VSCode에서 Nx 콘솔 열기
  3. 클릭 Generate (UI) "Common Nx Commands" 섹션에서
  4. 검색 @aws/nx-plugin - ts#nx-generator
  5. 필수 매개변수 입력
    • pluginProject: @aws/nx-plugin
    • name: ts#trpc-api#procedure
    • directory: trpc/procedure
    • description: Adds a procedure to a tRPC API
  6. 클릭 Generate

다음 파일들이 자동 생성됩니다:

  • 디렉터리packages/nx-plugin/src/trpc/procedure
    • schema.json 제너레이터 입력 정의
    • schema.d.ts 스키마와 일치하는 타입스크립트 인터페이스
    • generator.ts Nx가 실행하는 제너레이터 함수
    • generator.spec.ts 제너레이터 테스트
  • 디렉터리docs/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에 프로시저를 추가하려면 두 가지가 필요합니다:

  1. 새 프로시저용 타입스크립트 파일 생성
  2. 라우터에 프로시저 추가

새 프로시저용 타입스크립트 파일을 생성하기 위해 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 {};
});

템플릿에서 세 가지 변수를 참조했습니다:

  • procedureNameCamelCase
  • procedureNameKebabCase
  • procedureType

따라서 이 변수들을 generateFiles에 전달해야 하며, 파일을 생성할 디렉토리도 전달해야 합니다. 즉, 사용자가 제너레이터 입력으로 선택한 tRPC 프로젝트의 소스 파일 위치(sourceRoot)를 프로젝트 설정에서 추출할 수 있습니다.

제너레이터를 다음과 같이 업데이트합니다:

procedure/generator.ts
import {
generateFiles,
joinPathFragments,
readProjectConfiguration,
Tree,
} from '@nx/devkit';
import { TrpcProcedureSchema } from './schema';
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(__dirname, 'files'),
projectConfig.sourceRoot,
{
procedureNameCamelCase,
procedureNameKebabCase,
procedureType: options.type,
},
);
await formatFilesInSubtree(tree);
};
export default trpcProcedureGenerator;

다음으로 제너레이터가 새 프로시저를 라우터에 연결하도록 합니다. 이는 사용자의 소스 코드를 읽고 업데이트하는 것을 의미합니다!

TypeScript AST 조작을 사용하여 타입스크립트 소스 파일의 관련 부분을 업데이트합니다. 이를 조금 더 쉽게 만들기 위해 replacedestructuredImport라는 헬퍼가 있습니다.

procedure/generator.ts
import {
generateFiles,
joinPathFragments,
readProjectConfiguration,
Tree,
} from '@nx/devkit';
import { TrpcProcedureSchema } from './schema';
import { formatFilesInSubtree } from '../../utils/format';
import camelCase from 'lodash.camelcase';
import kebabCase from 'lodash.kebabcase';
import { destructuredImport, replace } from '../../utils/ast';
import { factory, ObjectLiteralExpression } from 'typescript';
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(__dirname, 'files'),
projectConfig.sourceRoot,
{
procedureNameCamelCase,
procedureNameKebabCase,
procedureType: options.type,
},
);
const routerPath = joinPathFragments(projectConfig.sourceRoot, 'router.ts');
destructuredImport(
tree,
routerPath,
[procedureNameCamelCase],
`./procedures/${procedureNameKebabCase}.js`,
);
replace(
tree,
routerPath,
'CallExpression[expression.name="router"] > ObjectLiteralExpression',
(node) =>
factory.createObjectLiteralExpression([
...(node as ObjectLiteralExpression).properties,
factory.createShorthandPropertyAssignment(procedureNameCamelCase),
]),
);
await formatFilesInSubtree(tree);
};
export default trpcProcedureGenerator;

제너레이터 구현을 완료했으니, 던전 어드벤처 프로젝트에서 테스트할 수 있도록 컴파일합니다.

Terminal window
pnpm nx run @aws/nx-plugin:compile

제너레이터를 테스트하기 위해 로컬 Nx Plugin for AWS를 기존 코드베이스에 연결합니다.

tRPC API가 있는 테스트 프로젝트 생성

섹션 제목: “tRPC API가 있는 테스트 프로젝트 생성”

별도의 디렉토리에서 새 테스트 워크스페이스를 생성합니다:

Terminal window
npx create-nx-workspace@22.4.2 trpc-generator-test --pm=pnpm --preset=@aws/nx-plugin --ci=skip --aiAgents

다음으로 프로시저를 추가할 tRPC API를 생성합니다:

  1. 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
  2. VSCode에서 Nx 콘솔 열기
  3. 클릭 Generate (UI) "Common Nx Commands" 섹션에서
  4. 검색 @aws/nx-plugin - ts#trpc-api
  5. 필수 매개변수 입력
    • apiName: test-api
  6. 클릭 Generate

코드베이스에서 로컬 @aws/nx-plugin을 연결합니다:

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

새 제너레이터를 실행해 봅니다:

  1. 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
  2. VSCode에서 Nx 콘솔 열기
  3. 클릭 Generate (UI) "Common Nx Commands" 섹션에서
  4. 검색 @aws/nx-plugin - ts#trpc-api#procedure
  5. 필수 매개변수 입력
    • 클릭 Generate

    성공하면 새 프로시저가 생성되고 router.ts의 라우터에 프로시저가 추가됩니다.

    여기까지 완료했고 Nx 제너레이터를 실험할 시간이 남았다면, 프로시저 제너레이터에 추가할 기능에 대한 제안 사항입니다:

    다음을 통해 중첩 라우터를 지원하도록 제너레이터를 업데이트해 보세요:

    • procedure 입력에 점 표기법 허용 (예: games.query)
    • 역방향 점 표기법 기반 프로시저 이름 생성 (예: queryGames)
    • 적절한 중첩 라우터 추가 (또는 이미 존재하는 경우 업데이트!)

    제너레이터는 사용자가 tRPC API가 아닌 project를 선택하는 것과 같은 잠재적 문제를 방어해야 합니다. 이에 대한 예시로 connection 제너레이터를 살펴보세요.

    제너레이터에 대한 단위 테스트를 작성하세요. 구현이 매우 간단하며 대부분 다음과 같은 일반적인 흐름을 따릅니다:

    1. createTreeUsingTsSolutionSetup()을 사용하여 빈 워크스페이스 트리 생성
    2. 트리에 이미 존재해야 하는 파일 추가 (예: tRPC 백엔드의 경우 project.jsonsrc/router.ts)
    3. 테스트 중인 제너레이터 실행
    4. 트리에 예상된 변경 사항이 적용되었는지 검증

    현재 모든 제너레이터를 실행하고 빌드가 성공하는지 확인하는 단일 “smoke test”가 있습니다. 이를 새 제너레이터를 포함하도록 업데이트해야 합니다.