Bỏ qua để đến nội dung

Đóng góp Generator

Hãy tạo một generator mới để đóng góp cho @aws/nx-plugin. Mục tiêu của chúng ta sẽ là tạo một procedure mới cho tRPC API.

Đầu tiên, hãy clone plugin:

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

Tiếp theo, cài đặt và build:

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

Hãy tạo generator mới trong packages/nx-plugin/src/trpc/procedure.

Chúng tôi cung cấp một generator để tạo các generator mới giúp bạn có thể nhanh chóng scaffold generator mới của mình! Bạn có thể chạy generator này như sau:

Terminal window
pnpm nx g @aws/nx-plugin:ts#nx-generator --project=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API
Bạn cũng có thể thực hiện chạy thử để xem những tệp nào sẽ bị thay đổi
Terminal window
pnpm nx g @aws/nx-plugin:ts#nx-generator --project=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API --dry-run

Bạn sẽ thấy các file sau đã được tạo cho bạn:

  • Thư mụcpackages/nx-plugin/src/trpc/procedure
    • schema.json Định nghĩa input cho generator
    • schema.d.ts Interface TypeScript khớp với schema
    • generator.ts Hàm mà Nx chạy như generator
    • generator.spec.ts Tests cho generator
  • Thư mụcdocs/src/content/docs/guides/
    • trpc-procedure.mdx Tài liệu cho generator
  • packages/nx-plugin/generators.json Đã được cập nhật để bao gồm generator

Hãy cập nhật schema để thêm các thuộc tính chúng ta cần cho generator:

{
"$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"]
}

Bạn sẽ thấy generator đã được kết nối trong 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"
}
},
...

Để thêm một procedure vào tRPC API, chúng ta cần làm hai việc:

  1. Tạo file TypeScript cho procedure mới
  2. Thêm procedure vào router

Để tạo file TypeScript cho procedure mới, chúng ta sẽ sử dụng một tiện ích gọi là generateFiles. Sử dụng nó, chúng ta có thể định nghĩa một template EJS mà chúng ta có thể render trong generator với các biến dựa trên các tùy chọn được người dùng chọn.

Đầu tiên, chúng ta sẽ định nghĩa template trong 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 {};
});

Trong template, chúng ta đã tham chiếu ba biến:

  • procedureNameCamelCase
  • procedureNameKebabCase
  • procedureType

Vì vậy chúng ta cần đảm bảo truyền những biến đó cho generateFiles, cùng với thư mục để tạo file vào, cụ thể là vị trí của các file nguồn (tức là sourceRoot) cho dự án tRPC mà người dùng đã chọn làm input cho generator, mà chúng ta có thể trích xuất từ cấu hình dự án.

Hãy cập nhật generator để làm điều đó:

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;

Tiếp theo, chúng ta muốn generator kết nối procedure mới vào router. Điều này có nghĩa là đọc và cập nhật mã nguồn của người dùng!

Chúng ta sử dụng GritQL để tìm kiếm và chuyển đổi mã nguồn một cách khai báo. Helper addDestructuredImport thêm các named import, và applyGritQL áp dụng một pattern GritQL để thêm procedure vào object literal của router.

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;

Bây giờ chúng ta đã triển khai generator, hãy compile nó để đảm bảo nó có sẵn cho chúng ta kiểm thử trong dự án dungeon adventure.

Terminal window
pnpm nx compile @aws/nx-plugin

Để kiểm thử generator, chúng ta sẽ liên kết Nx Plugin for AWS cục bộ của mình với một codebase hiện có.

Trong một thư mục riêng biệt, tạo một test workspace mới:

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

Tiếp theo, hãy tạo một tRPC API để thêm procedure vào:

Terminal window
pnpm nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactive
Bạn cũng có thể thực hiện chạy thử để xem những tệp nào sẽ bị thay đổi
Terminal window
pnpm nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactive --dry-run

Liên kết Nx Plugin for AWS cục bộ của chúng ta

Phần tiêu đề “Liên kết Nx Plugin for AWS cục bộ của chúng ta”

Trong codebase của bạn, hãy liên kết @aws/nx-plugin cục bộ của chúng ta:

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

Hãy thử generator mới:

Terminal window
pnpm nx g @aws/nx-plugin:ts#trpc-api#procedure
Bạn cũng có thể thực hiện chạy thử để xem những tệp nào sẽ bị thay đổi
Terminal window
pnpm nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-run

Nếu thành công, chúng ta sẽ đã tạo một procedure mới và thêm procedure vào router trong router.ts.

Nếu bạn đã đi đến đây và vẫn còn thời gian để thử nghiệm với Nx generator, đây là một số gợi ý về các tính năng để thêm vào procedure generator:

Thử cập nhật generator để hỗ trợ nested router bằng cách:

  • Chấp nhận ký hiệu dấu chấm cho input procedure (ví dụ: games.query)
  • Tạo một procedure với tên dựa trên ký hiệu dấu chấm đảo ngược (ví dụ: queryGames)
  • Thêm nested router phù hợp (hoặc cập nhật nó nếu nó đã tồn tại!)

Generator của chúng ta nên bảo vệ chống lại các vấn đề tiềm ẩn, chẳng hạn như người dùng chọn một project không phải là tRPC API. Hãy xem generator connection để có ví dụ về điều này.

Viết một số unit test cho generator. Chúng khá đơn giản để triển khai, và hầu hết đều tuân theo luồng chung:

  1. Tạo một empty workspace tree sử dụng createTreeUsingTsSolutionSetup()
  2. Thêm bất kỳ file nào đã tồn tại trong tree (ví dụ: project.jsonsrc/router.ts cho tRPC backend)
  3. Chạy generator đang được kiểm thử
  4. Xác thực các thay đổi mong đợi được thực hiện trên tree

Chúng tôi có một bộ “smoke tests” chạy các generator trong một workspace mới và đảm bảo rằng mọi thứ đều build được. Ở mức tối thiểu, generator mới của bạn nên được thêm vào cả hai generator matrix để nó được thực thi bởi smoke tests:

  • e2e/src/smoke-tests/generator-matrix.ts — chạy từng generator thông qua CLI, một lần gọi tại một thời điểm, chính xác như người dùng sẽ làm.
  • packages/nx-plugin/src/internal/test-matrix/generator.ts — một generator ẩn kết hợp tất cả các generator khác để kiểm thử migration giữa các phiên bản.

Lưu ý rằng generator matrix chỉ chạy các generator và build workspace — nó không khởi tạo bất kỳ infrastructure nào. Đối với các generator triển khai infrastructure, hãy xem xét mở rộng các deployment e2e tests (e2e/src/smoke-tests/cdk-deploy.spec.tsterraform-deploy.spec.ts) để thực sự triển khai các resource của bạn (thông qua cdk deploy / terraform apply), sau đó thêm một assertion vào deploy-invocations.ts để gọi resource đã triển khai và xác minh nó hoạt động như mong đợi.

Nếu generator của bạn cung cấp một local development server, hãy xem xét thêm nó vào local development e2e test (e2e/src/smoke-tests/local-dev.spec.ts), test này khởi động target dev và thực thi server đang chạy.

Hướng dẫn Chung để Tăng tốc Đóng góp

Phần tiêu đề “Hướng dẫn Chung để Tăng tốc Đóng góp”

Phần này chứa một số hướng dẫn chung có thể giúp ích khi làm việc với Nx Plugin for AWS.

Một cách hữu ích để xây dựng các generator mới hoặc thêm tính năng/sửa lỗi cho một generator hiện có là xây dựng nó thực sự trước. Bằng cách này, bạn có thể xác thực ý tưởng của mình và lặp lại nhanh chóng để đạt được chức năng bạn cần. Sau khi bạn đã quyết định kết quả mong muốn, bạn có thể cập nhật generator.

Trong thực tế, quy trình này có thể trông như sau:

  1. Tạo một workspace mới

    Terminal window
    pnpm create @aws/nx-workspace my-project
  2. Chạy bất kỳ generator nào có thể là điều kiện tiên quyết cho generator/tính năng/sửa lỗi mới của bạn

  3. Commit các thay đổi của bạn (git commit)

  4. Thực hiện các thay đổi mong muốn và kiểm thử chúng khi cần

  5. Sử dụng git diff của các thay đổi để thông báo những thay đổi nào nên được thực hiện cho Nx Plugin for AWS

  6. Thực hiện một lần kiểm thử end to end cuối cùng (liên kết @aws/nx-plugin của bạn) để đảm bảo generator của bạn cung cấp các thay đổi bạn cần