贡献生成器
让我们为@aws/nx-plugin创建一个新的生成器来贡献代码。我们的目标是为tRPC API生成新的procedure。
首先克隆插件仓库:
git clone git@github.com:awslabs/nx-plugin-for-aws.git安装依赖并构建:
cd nx-plugin-for-awspnpm ipnpm nx run-many --target build --all创建空生成器
Section titled “创建空生成器”在packages/nx-plugin/src/trpc/procedure目录下创建新生成器。
我们提供了创建生成器的生成器,可以快速搭建新生成器!运行以下命令:
- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@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
- 点击
Generate
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 APIyarn 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 APInpx 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 APIbunx 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您还可以执行试运行以查看哪些文件会被更改
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-runyarn 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-runnpx 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-runbunx 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以下文件已自动生成:
文件夹packages/nx-plugin/src/trpc/procedure
- schema.json 定义生成器输入
- schema.d.ts 与schema匹配的TypeScript接口
- generator.ts Nx运行的生成器函数
- generator.spec.ts 生成器测试
文件夹docs/src/content/docs/guides/
- trpc-procedure.mdx 生成器文档
- packages/nx-plugin/generators.json 更新包含生成器
更新schema添加生成器所需属性:
{ "$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"]}export interface TrpcProcedureSchema { project: string; procedure: string; type: 'query' | 'mutation';}生成器已自动注册到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添加procedure需要完成两个步骤:
- 创建新procedure的TypeScript文件
- 将procedure添加到router
创建新Procedure
Section titled “创建新Procedure”使用generateFiles工具创建TypeScript文件。通过EJS模板根据用户选项生成内容。
在packages/nx-plugin/src/trpc/procedure/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 {}; });模板中引用了三个变量:
procedureNameCamelCaseprocedureNameKebabCaseprocedureType
需要将这些变量传递给generateFiles,并确定生成文件的目标目录(即用户选择的tRPC项目的源码目录)。
更新生成器代码:
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;将Procedure添加到Router
Section titled “将Procedure添加到Router”需要读取并修改用户源码中的router文件。使用TypeScript AST操作工具来更新代码。
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;编译生成器使其可用:
pnpm nx run @aws/nx-plugin:compile将本地Nx Plugin for AWS链接到现有代码库进行测试。
创建包含tRPC API的测试项目
Section titled “创建包含tRPC API的测试项目”在新目录创建测试工作区:
npx create-nx-workspace@21.6.5 trpc-generator-test --pm=pnpm --preset=@aws/nx-plugin --ci=skip --aiAgentsnpx create-nx-workspace@21.6.5 trpc-generator-test --pm=yarn --preset=@aws/nx-plugin --ci=skip --aiAgentsnpx create-nx-workspace@21.6.5 trpc-generator-test --pm=npm --preset=@aws/nx-plugin --ci=skip --aiAgentsnpx create-nx-workspace@21.6.5 trpc-generator-test --pm=bun --preset=@aws/nx-plugin --ci=skip --aiAgents生成tRPC API:
- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - ts#trpc-api - 填写必需参数
- apiName: test-api
- 点击
Generate
pnpm nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactiveyarn nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactivenpx nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactivebunx nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive您还可以执行试运行以查看哪些文件会被更改
pnpm nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive --dry-runyarn nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive --dry-runnpx nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive --dry-runbunx nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive --dry-run链接本地Nx Plugin
Section titled “链接本地Nx Plugin”链接本地@aws/nx-plugin:
cd path/to/trpc-generator-testpnpm link path/to/nx-plugin-for-aws/dist/packages/nx-plugincd path/to/trpc-generator-testyarn link path/to/nx-plugin-for-aws/dist/packages/nx-plugincd path/to/trpc-generator-testnpm link path/to/nx-plugin-for-aws/dist/packages/nx-plugincd path/to/nx-plugin-for-aws/dist/packages/nx-pluginbun linkcd path/to/trpc-generator-testbun link @aws/nx-plugin运行新生成器
Section titled “运行新生成器”执行新生成器:
- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - ts#trpc-api#procedure - 填写必需参数
- 点击
Generate
pnpm nx g @aws/nx-plugin:ts#trpc-api#procedureyarn nx g @aws/nx-plugin:ts#trpc-api#procedurenpx nx g @aws/nx-plugin:ts#trpc-api#procedurebunx nx g @aws/nx-plugin:ts#trpc-api#procedure您还可以执行试运行以查看哪些文件会被更改
pnpm nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-runyarn nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-runnpx nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-runbunx nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-run成功运行后,将生成新procedure并添加到router.ts中。
如需进一步探索Nx生成器,可尝试以下功能增强:
1. 嵌套操作
Section titled “1. 嵌套操作”支持嵌套router:
- 允许
procedure输入使用点符号(如games.query) - 根据反转点符号生成procedure名称(如
queryGames) - 添加或更新嵌套router
防止用户选择非tRPC项目,可参考api-connection生成器的实现。
3. 单元测试
Section titled “3. 单元测试”编写生成器单元测试:
- 使用
createTreeUsingTsSolutionSetup()创建空工作区树 - 添加预存文件(如
project.json和src/router.ts) - 运行生成器
- 验证树结构变更
4. 端到端测试
Section titled “4. 端到端测试”当前”smoke test”仅验证构建成功,需更新测试包含新生成器。