crud-di

star 341

PowerX CRUD 依赖注入规则(Deps 单入口、构造注入、跨传输复用)。

ArtisanCloud By ArtisanCloud schedule Updated 3/25/2026

name: crud-di description: PowerX CRUD 依赖注入规则(Deps 单入口、构造注入、跨传输复用)。

PowerX CRUD DI

步骤

  1. 打开 本文件内嵌规则
  2. 按规则执行实现/校对。
  3. 完成后按核对清单验收。

核对点

  • 与 PowerX 当前代码结构、路径与命名一致。
  • 仅在传输层/契约层做职责内改动,不跨层越界。

规则(内嵌)

di.yaml

kind: ruleset
name: crud_di
version: 1.0.0
owner: powerx
status: stable

meta:
  intent: >
    统一依赖注入装配:Deps 作为单一入口,Service/Repo/Handler 经构造函数注入;
    禁止在 Handler/Service 中直接 new 外部客户端或直连 DB;支持 HTTP/GRPC/MQ 等多传输共用同一业务服务。
  references:
    - constitution.md
    - dev_crud_http_guides.md

scope:
  codebase:
    deps_file: "internal/app/shared/deps.go"
    service_globs:
      - "internal/service/**/**_service.go"
    repo_globs:
      - "internal/repository/**/**_repo.go"
    handler_globs:
      - "internal/transport/http/**/**_handler.go"
    grpc_server_globs:
      - "internal/transport/grpc/**/**.go"

principles:
  - Deps 为“服务容器”:提供 DB/Logger/Cache/EventBus/KeyRing/Config 等基础依赖。
  - 构造函数注入:NewXxxService(NewXxxRepo(...));禁止全局单例与包级可变状态。
  - 传输解耦:HTTP/GRPC 层仅持有 Service;Service 不感知传输实现。
  - 生命周期统一:Deps 负责启动/关闭顺序(DB→Repo/Service→Transport)。

checks:
  - id: deps.file.exists
    level: error
    when: { file: "internal/app/shared/deps.go" }
    assert:
      - must_define: "type Deps struct"
      - must_define: "func NewDeps() (*Deps, error)"
  - id: service.constructor
    level: error
    when: { glob: "internal/service/**/**_service.go" }
    assert:
      - must_define_like: "func New*Service(*Deps) *"
      - must_not_import: ["database/sql","gorm.io/gorm"]   # Service 通过 deps 间接持有 DB
  - id: repo.constructor
    level: error
    when: { glob: "internal/repository/**/**_repo.go" }
    assert:
      - must_define_like: "func New*Repo(*gorm.DB) *"
  - id: handler.depends_on_service_only
    level: error
    when: { glob: "internal/transport/http/**/**_handler.go" }
    assert:
      - must_define_like: "type *Handler struct { svc *service.* }"
      - must_define_like: "func New*Handler(*service.*) *"
      - must_not_import: ["gorm.io/gorm","database/sql","net/http"]
  - id: grpc.server.uses_service
    level: warn
    when: { glob: "internal/transport/grpc/**/**.go" }
    assert:
      - should_contain: "deps.*Service"   # gRPC 服务实现注入 Service,而非直连 Repo/DB
  - id: deps.no_new_external_in_handlers
    level: error
    when: { glob: "internal/transport/http/**/**_handler.go" }
    assert:
      - must_not_call: ["redis.NewClient(","kafka.NewReader(","http.DefaultClient.Do"]

acceptance:
  checklist:
    - "[ ] internal/app/shared/deps.go 定义 Deps 与 NewDeps"
    - "[ ] Service/Repo/Handler 均提供 New* 构造函数"
    - "[ ] Handler/GRPC 层仅依赖 Service,不直连 Repo/DB/外部客户端"
    - "[ ] Deps 提供 DB/Logger/Cache/EventBus/KeyRing/Config 等公共依赖"
    - "[ ] 无全局可变单例;关闭顺序由 Deps 统一管理"

templates:
  deps_go: |
    // internal/app/shared/deps.go
    package shared

    import (
      "context"
      "gorm.io/gorm"
      "github.com/redis/go-redis/v9"
      "log"
    )

    type Deps struct {
      DB      *gorm.DB
      Redis   *redis.Client
      Logger  *log.Logger
      // EventBus  any
      // KeyRing   any  // 与 STS 对齐的验签/加密材料
      // Config    *Config
      // Tracer    trace.Tracer
      // ...
      // 业务服务
      {{Entity}}Service *{{domain}}.{{Entity}}Service
    }

    func NewDeps() (*Deps, error) {
      // 1) 初始化基础设施(DB/Cache/Logger/...)
      db := mustOpenDB()
      rdb := mustOpenRedis()
      logger := mustLogger()

      d := &Deps{DB: db, Redis: rdb, Logger: logger}

      // 2) 初始化 Repository & Service
      {{entity}}Repo := {{domain}}repo.New{{Entity}}Repo(d.DB)
      d.{{Entity}}Service = {{domain}}svc.New{{Entity}}Service(d, {{entity}}Repo)

      return d, nil
    }

    func (d *Deps) Close(ctx context.Context) error {
      // 逆序关闭资源
      if d.Redis != nil { _ = d.Redis.Close() }
      // if d.DB != nil { sqlDB, _ := d.DB.DB(); _ = sqlDB.Close() }
      return nil
    }
  service_go: |
    // internal/service/{{domain}}/{{resource}}_service.go
    package {{domain}}svc

    import "github.com/ArtisanCloud/PowerX/internal/app/shared"

    type {{Entity}}Service struct {
      deps *shared.Deps
      repo {{domain}}repo.{{Entity}}Repo
    }

    func New{{Entity}}Service(d *shared.Deps, r {{domain}}repo.{{Entity}}Repo) *{{Entity}}Service {
      return &{{Entity}}Service{deps: d, repo: r}
    }
  repo_go: |
    // internal/repository/{{domain}}/{{resource}}_repo.go
    package {{domain}}repo

    import "gorm.io/gorm"

    type {{Entity}}Repo interface {
      // 定义接口方法
    }

    type {{Entity}}RepoImpl struct {
      db *gorm.DB
    }

    func New{{Entity}}Repo(db *gorm.DB) {{Entity}}Repo {
      return &{{Entity}}RepoImpl{db: db}
    }
  wire_in_api_go: |
    // internal/transport/http/{{layer}}/{{domain}}/api.go
    func Register{{Domain}}Routes(rg *gin.RouterGroup, deps *shared.Deps) {
      h := New{{Entity}}Handler(deps.{{Entity}}Service)
      g := rg.Group("/{{domain}}/{{resource}}")
      {
        g.POST("", h.Create)
        g.GET("", h.List)
        g.GET("/:id", h.Get)
        g.PATCH("/:id", h.Update)
        g.DELETE("/:id", h.Delete)
      }
    }
Install via CLI
npx skills add https://github.com/ArtisanCloud/PowerX --skill crud-di
Repository Details
star Stars 341
call_split Forks 63
navigation Branch main
article Path SKILL.md
More from Creator
ArtisanCloud
ArtisanCloud Explore all skills →