mcpField
V
vendure-developing

vendure-developing

github.com/meriley开发41 次安装
代码仓库

关于 vendure-developing

Vendure Development 是面向 Vendure 项目开发者的开发入口技能,适用于构建或审查 Vendure 项目。它提供架构参考、编码模式,并指导通过 vendure-expert Agent 协调专门技能。

主要功能

  1. 01覆盖六个 Vendure 领域的速查
  2. 02插件与 GraphQL 模式指南
  3. 03实体和数据库实现指南
  4. 04Admin UI 扩展模式
  5. 05通过 vendure-expert 协调专门技能

适用场景

  1. 01开始实现 Vendure 插件
  2. 02扩展 Shop 或 Admin GraphQL API
  3. 03构建实体并创建数据库迁移
  4. 04按安全和规范审查插件代码

MCP 相关

README 提到通过类似 MCP 工具名称的接口访问 Context7 文档,但未将此技能描述为 MCP 服务或客户端。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/meriley/claude-code-skills --skill vendure-developing

安装后在 Claude Code 中输入/vendure-developing确认已加载。

详细介绍

Vendure 开发

用途

所有 Vendure 开发任务的入口。为 vendure-expert Agent 提供快速参考和指南,以便协调多个领域的指导。

不适用场景

  • 非 Vendure 电商平台(Shopify、Magento 等)
  • 不涉及 Vendure 的基础 TypeScript/NestJS
  • 不涉及 Vendure Admin UI 的纯前端 React

快速开始:使用 Agent

如需全面的 Vendure 指导,请使用 vendure-expert Agent:

Task(subagent_type: "vendure-expert", prompt: "Your Vendure task here")

该 Agent 协调 9 项专业技能:

  • 插件开发(编写 + 审查)
  • GraphQL API(编写 + 审查)
  • 实体/数据库(编写 + 审查)
  • Admin UI(编写 + 审查)
  • 配送/运输功能(专项)

Vendure 架构速查

6 个核心领域
领域核心概念
插件@VendurePlugin、NestJS DI、生命周期钩子
GraphQL双 API(Shop/Admin)、RequestContext、gql 模板
实体VendureEntity、TypeORM、迁移、自定义字段
Admin UIReact/Angular、UI DevKit、延迟加载
策略InjectableStrategy、自定义逻辑
事件EventBus、事务安全的订阅
插件脚手架
import { PluginCommonModule, VendurePlugin } from "@vendure/core";

@VendurePlugin({
  imports: [PluginCommonModule],
  providers: [MyService],
  entities: [MyEntity],
  adminApiExtensions: {
    schema: gql`...`,
    resolvers: [MyResolver],
  },
})
export class MyPlugin {
  static init(options: MyPluginOptions) {
    this.options = options;
    return MyPlugin;
  }
}
GraphQL Resolver 模式
import { Ctx, RequestContext, Query, Resolver } from "@vendure/core";
import { Allow, Permission } from "@vendure/core";

@Resolver()
export class MyResolver {
  constructor(private myService: MyService) {}

  @Query()
  @Allow(Permission.ReadSettings)
  async myQuery(@Ctx() ctx: RequestContext): Promise<MyType[]> {
    return this.myService.findAll(ctx);
  }
}
实体模式
import { VendureEntity, DeepPartial } from "@vendure/core";
import { Entity, Column, ManyToOne } from "typeorm";

@Entity()
export class MyEntity extends VendureEntity {
  constructor(input?: DeepPartial<MyEntity>) {
    super(input);
  }

  @Column()
  name: string;

  @ManyToOne(() => OtherEntity)
  relation: OtherEntity;
}
Admin UI 扩展
// providers.ts
import { addNavMenuSection } from "@vendure/admin-ui/react";

export default [
  addNavMenuSection(
    {
      id: "my-section",
      label: "My Feature",
      items: [
        {
          id: "my-page",
          label: "My Page",
          routerLink: ["/extensions/my-feature"],
          icon: "cog",
        },
      ],
    },
    "settings",
  ),
];

禁止使用的模式

插件开发
  • 缺少 @VendurePlugin 装饰器
  • 未使用 NestJS DI(@Injectable)
  • 使用硬编码值,而非插件配置
  • 绕过服务直接访问数据库
GraphQL
  • 缺少 @Ctx() RequestContext 参数
  • 绕过 @Allow() 权限装饰器
  • 混用 Shop/Admin 架构类型
  • 未使用 gql 模板字面量
实体
  • 未继承 VendureEntity
  • 缺少 @Entity() 装饰器
  • 未创建迁移文件
  • 使用 any 类型
Admin UI
  • 未对路由进行延迟加载
  • 使用硬编码字符串(未使用 i18n)
  • 缺少加载/错误状态
  • 未处理权限

必须遵循的模式

RequestContext 传递
// ALWAYS pass ctx through service calls
async myResolver(@Ctx() ctx: RequestContext) {
  return this.service.findAll(ctx);  // Pass ctx!
}
权限装饰器
@Query()
@Allow(Permission.ReadCatalog)  // ALWAYS specify permissions
async products(@Ctx() ctx: RequestContext) { }
实体输入类型
// Use DeepPartial for constructor input
constructor(input?: DeepPartial<MyEntity>) {
  super(input);
}
InputMaybe 处理
// Check BOTH undefined AND null for GraphQL inputs
if (input.field !== undefined && input.field !== null) {
  entity.field = input.field;
}

领域技能决策树

Task Type
    │
    ├─> Creating/modifying plugin structure
    │   └─> vendure-plugin-writing
    │
    ├─> Reviewing plugin code
    │   └─> vendure-plugin-reviewing
    │
    ├─> Extending GraphQL schema or resolvers
    │   └─> vendure-graphql-writing
    │
    ├─> Reviewing GraphQL code
    │   └─> vendure-graphql-reviewing
    │
    ├─> Creating/modifying entities
    │   └─> vendure-entity-writing
    │
    ├─> Reviewing entity definitions
    │   └─> vendure-entity-reviewing
    │
    ├─> Building Admin UI components
    │   └─> vendure-admin-ui-writing
    │
    ├─> Reviewing Admin UI code
    │   └─> vendure-admin-ui-reviewing
    │
    └─> Delivery/shipping features
        └─> vendure-delivery-plugin

常见模式

双 API 分离
// Admin API - full access
export const graphqlAdminSchema = gql`
  extend type Query {
    myAdminQuery: [MyType!]!
  }
  extend type Mutation {
    updateMyType(input: UpdateInput!): MyType!
  }
`;

// Shop API - customer-facing, read-only or limited
export const graphqlShopSchema = gql`
  extend type Query {
    myPublicQuery: [MyType!]!
  }
`;
带 RequestContext 的服务模式
@Injectable()
export class MyService {
  constructor(private connection: TransactionalConnection) {}

  async findAll(ctx: RequestContext): Promise<MyEntity[]> {
    return this.connection.getRepository(ctx, MyEntity).find();
  }

  async create(ctx: RequestContext, input: CreateInput): Promise<MyEntity> {
    const entity = new MyEntity(input);
    return this.connection.getRepository(ctx, MyEntity).save(entity);
  }
}
事务装饰器
@Mutation()
@Transaction()  // Wrap in database transaction
@Allow(Permission.UpdateSettings)
async updateMyEntity(
  @Ctx() ctx: RequestContext,
  @Args() { input }: { input: UpdateInput }
): Promise<MyEntity> {
  return this.service.update(ctx, input);
}

示例

示例 1:创建简单插件

任务: 创建一个用于跟踪产品浏览量的插件。

方法:

  1. 使用 vendure-plugin-writing 搭建插件脚手架
  2. 使用 vendure-entity-writing 创建 ProductView 实体
  3. 使用 vendure-graphql-writing 扩展查询

结果:

@VendurePlugin({
  imports: [PluginCommonModule],
  entities: [ProductViewEntity],
  providers: [ProductViewService],
  shopApiExtensions: {
    schema: gql`
      extend type Query {
        productViews(productId: ID!): Int!
      }
    `,
    resolvers: [ProductViewResolver],
  },
})
export class ProductViewsPlugin {}
示例 2:添加 Admin UI 页面

任务: 添加一个用于管理插件配置的设置页面。

方法:

  1. 使用 vendure-admin-ui-writing 编写 React 组件
  2. 注册路由和导航项
  3. 使用 DataService 调用 API

结果:

// pages/SettingsPage.tsx
export function SettingsPage() {
  const dataService = useInjector(DataService);
  const [settings, setSettings] = useState<Settings>();

  useEffect(() => {
    dataService
      .query(GetSettingsDocument)
      .stream$.subscribe((result) => setSettings(result.mySettings));
  }, []);

  return <SettingsForm settings={settings} />;
}
示例 3:审查插件代码

任务: 审查插件的安全性和最佳实践。

方法:

  1. 使用 vendure-plugin-reviewing 检查插件结构
  2. 使用 vendure-graphql-reviewing 检查 resolver 模式
  3. 使用 vendure-entity-reviewing 检查数据库模式

检查项:

  • 所有服务调用都传递了 RequestContext
  • 所有 resolver 都声明了权限
  • 没有直接执行数据库查询(使用 TransactionalConnection)
  • 正确处理错误

故障排查

问题原因解决方案
未找到实体不在插件实体数组中添加到 @VendurePlugin({ entities: [] })
未调用解析器不在 resolvers 数组中添加到 apiExtensions.resolvers
权限被拒绝缺少 @Allow 装饰器添加 @Allow(Permission.X)
TypeScript 错误导入路径错误从 @vendure/core 导入
管理界面未加载未延迟加载对路由使用 React.lazy()

外部文档

Context7(推荐)
mcp__context7__get-library-docs
context7CompatibleLibraryID: "/vendure-ecommerce/vendure"
topic: "plugins" or "entities" or "graphql" etc.
官方文档

相关 Agent

如需全面的多领域 Vendure 指南,请使用 vendure-expert Agent。

该 Agent 协调全部 9 项 Vendure 技能,并提供:

  • 完整的插件生命周期指南
  • 安全与质量审计
  • 最佳实践规范
  • 特定领域的模式

评论

支持 Markdown