Agent SkillsOpenAEV-Platform/openaev › create-feature-module

create-feature-module

GitHub

用于从零开始生成完整后端功能模块及前端页面的脚手架工具,涵盖实体、服务、控制器、测试及迁移脚本的自动化创建。

.github/skills/create-feature-module/SKILL.md OpenAEV-Platform/openaev

Trigger Scenarios

用户请求创建新功能或模块 需要生成包含前后端的完整业务代码

Install

npx skills add OpenAEV-Platform/openaev --skill create-feature-module -g -y
More Options

Non-standard path

npx skills add https://github.com/OpenAEV-Platform/openaev/tree/main/.github/skills/create-feature-module -g -y

Use without installing

npx skills use OpenAEV-Platform/openaev@create-feature-module

指定 Agent (Claude Code)

npx skills add OpenAEV-Platform/openaev --skill create-feature-module -a claude-code -g -y

安装 repo 全部 skill

npx skills add OpenAEV-Platform/openaev --all -g -y

预览 repo 内 skill

npx skills add OpenAEV-Platform/openaev --list

SKILL.md

Frontmatter
{
    "name": "create-feature-module",
    "description": "Scaffolds a complete feature end-to-end: JPA entity, repository, service, DTOs, mapper, controller, migration, tests (fixture + composer + integration test), and frontend actions\/page. Use when asked to create a new feature or module."
}

Create Feature Module

Prerequisites

  • Entity name (singular, e.g. PlatformGroup)
  • Table name (plural snake_case, e.g. platform_groups)
  • Tenancy scope: tenant-scoped, platform-level, or dual-scope
  • Fields with types and constraints

Checkpoint: Scope Confirmation

Before writing any code, present the following to the user and wait for confirmation:

  • Entity name and table name
  • Tenancy scope: tenant-scoped, platform-level, or dual-scope
  • Fields: name, type, constraints, nullable
  • Files to create: list every file (entity, repository, service, DTOs, mapper, controller, migration, test fixtures, integration test, frontend actions/page)
  • Instruction files read: confirm you have read the relevant .github/instructions/ files for all layers involved

Do not proceed until the user confirms the scope is correct.

Procedure

Step 1 — Create the JPA Entity

Location: openaev-model/src/main/java/io/openaev/database/model/

Follow Group.java (tenant-scoped) or Tenant.java (platform-level):

  • @ControlledUuidGeneration for ID
  • @Queryable on filterable fields
  • @Transient @JsonIgnore ResourceType field
  • Collections initialized as mutable (new ArrayList<>())
  • Follow conventions from database.instructions.md

If dual-scope (Settings, User, Role, Group pattern):

  • Implement DualScopeBase interface
  • Use ModelBaseListener only (no TenantBaseListener)
  • Do NOT add @Filter("tenantFilter")
  • tenant_id must be nullable: @JoinColumn(name = "tenant_id", nullable = true)
  • @JsonIgnore on the tenant relation

Step 2 — Create the Repository

Location: openaev-model/src/main/java/io/openaev/database/repository/

public interface {Entity}Repository extends JpaRepository<{Entity}, String>,
    JpaSpecificationExecutor<{Entity}> {}

Step 3 — Add ResourceType + Capabilities

  • Add value in ResourceType.java
  • Add ACCESS_, MANAGE_, DELETE_ in Capability.java with parent hierarchy

Checkpoint: Entity Layer Review

After completing Steps 1–3, present the following to the user and wait for confirmation:

  • Entity class: field names, column names, annotations, tenant scope
  • ResourceType and Capability additions: exact enum values and hierarchy
  • Repository: confirm interface signature

Do not proceed to the service/API/frontend layers until the user confirms the entity layer is correct.

Step 4 — Create the Service

Location: openaev-api/src/main/java/io/openaev/service/

  • @Service @RequiredArgsConstructor @Transactional(rollbackFor = Exception.class)
  • CRUD + search with pagination
  • JavaDoc on all public methods

If dual-scope — create TWO services:

  • Platform{Entity}Service — all queries use findByTenantIsNull() variants, never receives tenantId
  • Tenant{Entity}Service — all queries use findByTenantId(tenantId) variants, receives tenantId as argument
  • See multi-tenancy.instructions.md → Dual-Scope Entities for full pattern

Step 5 — Create DTOs + Mapper

Location: openaev-api/src/main/java/io/openaev/api/{feature}/

  • {Entity}Input and {Entity}Output as Java record
  • {Entity}Mapper with static fromInput() + toOutput()

Step 6 — Create the Controller

Location: openaev-api/src/main/java/io/openaev/api/{feature}/

  • @AccessControl + @LogExecutionTime + @Operation on every endpoint
  • CRUD + search endpoints
  • All new tenant-scoped APIs use TENANT_PREFIX: @RequestMapping(TENANT_PREFIX + "/{entities}") → resolves to /api/tenants/{tenantId}/{entities}

If dual-scope — create TWO controllers:

  • Platform{Entity}Api at /api/platform-{entities} — uses Platform{Entity}Service, platform-admin @AccessControl
  • Tenant{Entity}Api at TENANT_PREFIX + "/{entities}" — tenant ID extracted from URL path, passed to Tenant{Entity}Service

Step 7 — Create the Migration

Location: openaev-api/src/main/java/io/openaev/migration/

  • Find next version number in existing migrations
  • CREATE TABLE, FK constraints, indexes

If dual-scope:

  • tenant_id VARCHAR(255)nullable, FK to tenants(tenant_id) ON DELETE CASCADE
  • Partial unique indexes:
    CREATE UNIQUE INDEX uk_{table}_name_platform ON {table} ({field}) WHERE tenant_id IS NULL;
    CREATE UNIQUE INDEX uk_{table}_name_tenant ON {table} ({field}, tenant_id) WHERE tenant_id IS NOT NULL;
    

Step 8 — Create Test Fixtures + Composer

Location: openaev-api/src/test/java/io/openaev/utils/fixtures/

  • Fixture: createDefault{Entity}() with random names
  • Composer: extends ComposerBase, inner Composer class

If dual-scope:

  • Fixture must support both: createDefaultPlatform{Entity}() (tenant = null) and createDefaultTenant{Entity}(String tenantId)

Step 9 — Create Integration Test

Location: openaev-api/src/test/java/io/openaev/api/{feature}/

  • @Nested @DisplayName groups, @WithMockUser, assertThatJson

If dual-scope — add isolation tests:

  • given_platformEntity_should_notAppearInTenantList
  • given_tenantEntity_should_notAppearInPlatformList
  • given_tenantA_should_notSeeTenantBEntities
  • Test both Platform{Entity}Api and Tenant{Entity}Api independently

Step 10 — Create Frontend Actions + Page

Follow templates and conventions from frontend.instructions.md.

Location: openaev-front/src/actions/{feature}/ and src/admin/components/

  • {feature}-action.ts — API calls (CRUD + search)
  • {feature}-helper.d.ts — TypeScript types (or use auto-generated api-types.d.ts)
  • {feature}-schema.ts — Zod validation schema
  • List page with Queryable + DataTable
  • Create/Edit form with React Hook Form + Zod
  • Permission guards with CASL (ability.can(ACTIONS.MANAGE, SUBJECTS.X))

Step 11 — Verify

mvn spotless:apply
mvn test
cd openaev-front && yarn lint && yarn check-ts && yarn test

Version History

  • 3.260818.1 Current 2026-08-20 12:00

Same Skill Collection

.github/skills/add-contract-output-type/SKILL.md
.github/skills/add-migration/SKILL.md
.github/skills/add-test/SKILL.md
.github/skills/reduce-tx-baseline/SKILL.md
.github/skills/review-code/SKILL.md
.github/skills/review-docs/SKILL.md
.github/skills/review-frontend/SKILL.md
.github/skills/review-migration/SKILL.md
.github/skills/review-multi-tenancy/SKILL.md
.github/skills/review-performance/SKILL.md
.github/skills/review-security/SKILL.md
.github/skills/activate-tenant-table/SKILL.md

Metadata

Files
0
Version
3.260818.1
Hash
670ccca6
Indexed
2026-08-20 12:00

- 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-25 10:41
浙ICP备14020137号-1 $방문자$