vendure-developing
1
总安装量
1
周安装量
#47122
全站排名
安装命令
npx skills add https://github.com/meriley/claude-code-skills --skill vendure-developing
Agent 安装分布
pi
1
opencode
1
cursor
1
codex
1
claude-code
1
gemini-cli
1
Skill 文档
Vendure Development
Purpose
Entry point for all Vendure development tasks. Provides quick reference and guides to the vendure-expert agent for coordinated multi-domain guidance.
When NOT to Use
- Non-Vendure e-commerce platforms (Shopify, Magento, etc.)
- Basic TypeScript/NestJS without Vendure context
- Frontend-only React without Vendure Admin UI
Quick Start: Use the Agent
For comprehensive Vendure guidance, use the vendure-expert agent:
Task(subagent_type: "vendure-expert", prompt: "Your Vendure task here")
The agent coordinates 9 specialized skills:
- Plugin development (writing + reviewing)
- GraphQL API (writing + reviewing)
- Entity/Database (writing + reviewing)
- Admin UI (writing + reviewing)
- Delivery/shipping features (specialized)
Vendure Architecture Quick Reference
6 Core Domains
| Domain | Key Concepts |
|---|---|
| Plugins | @VendurePlugin, NestJS DI, lifecycle hooks |
| GraphQL | Dual APIs (Shop/Admin), RequestContext, gql template |
| Entities | VendureEntity, TypeORM, migrations, custom fields |
| Admin UI | React/Angular, UI DevKit, lazy loading |
| Strategies | InjectableStrategy, custom logic |
| Events | EventBus, transaction-safe subscriptions |
Plugin Scaffold
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 Pattern
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);
}
}
Entity Pattern
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 Extension
// 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",
),
];
FORBIDDEN Patterns
Plugin Development
- Missing @VendurePlugin decorator
- Not using NestJS DI (@Injectable)
- Hardcoded values instead of plugin config
- Direct database access bypassing services
GraphQL
- Missing @Ctx() RequestContext parameter
- Bypassing @Allow() permission decorator
- Mixing Shop/Admin schema types
- Not using gql template literal
Entities
- Not extending VendureEntity
- Missing @Entity() decorator
- No migration file created
- Using
anytype
Admin UI
- Not lazy loading routes
- Hardcoded strings (not using i18n)
- Missing loading/error states
- Not handling permissions
REQUIRED Patterns
RequestContext Threading
// ALWAYS pass ctx through service calls
async myResolver(@Ctx() ctx: RequestContext) {
return this.service.findAll(ctx); // Pass ctx!
}
Permission Decorators
@Query()
@Allow(Permission.ReadCatalog) // ALWAYS specify permissions
async products(@Ctx() ctx: RequestContext) { }
Entity Input Types
// Use DeepPartial for constructor input
constructor(input?: DeepPartial<MyEntity>) {
super(input);
}
InputMaybe Handling
// Check BOTH undefined AND null for GraphQL inputs
if (input.field !== undefined && input.field !== null) {
entity.field = input.field;
}
Domain Skill Decision Tree
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
Common Patterns
Dual API Separation
// 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!]!
}
`;
Service Pattern with 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);
}
}
Transaction Decorator
@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);
}
Examples
Example 1: Create a Simple Plugin
Task: Create a plugin that tracks product views.
Approach:
- Use vendure-plugin-writing for plugin scaffold
- Use vendure-entity-writing for ProductView entity
- Use vendure-graphql-writing for query extension
Result:
@VendurePlugin({
imports: [PluginCommonModule],
entities: [ProductViewEntity],
providers: [ProductViewService],
shopApiExtensions: {
schema: gql`
extend type Query {
productViews(productId: ID!): Int!
}
`,
resolvers: [ProductViewResolver],
},
})
export class ProductViewsPlugin {}
Example 2: Add Admin UI Page
Task: Add a settings page to manage plugin configuration.
Approach:
- Use vendure-admin-ui-writing for React components
- Register route and navigation item
- Use DataService for API calls
Result:
// 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} />;
}
Example 3: Review Plugin Code
Task: Audit a plugin for security and best practices.
Approach:
- Use vendure-plugin-reviewing for plugin structure
- Use vendure-graphql-reviewing for resolver patterns
- Use vendure-entity-reviewing for database patterns
Checks:
- RequestContext passed through all service calls
- Permissions declared on all resolvers
- No direct database queries (use TransactionalConnection)
- Proper error handling
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
| Entity not found | Not in plugin entities array | Add to @VendurePlugin({ entities: [] }) |
| Resolver not called | Not in resolvers array | Add to apiExtensions.resolvers |
| Permission denied | Missing @Allow decorator | Add @Allow(Permission.X) |
| TypeScript errors | Wrong import path | Import from @vendure/core |
| Admin UI not loading | Not lazy loaded | Use React.lazy() for routes |
External Documentation
Context7 (Recommended)
mcp__context7__get-library-docs
context7CompatibleLibraryID: "/vendure-ecommerce/vendure"
topic: "plugins" or "entities" or "graphql" etc.
Official Docs
Related Agent
For comprehensive multi-domain Vendure guidance, use the vendure-expert agent.
The agent coordinates all 9 Vendure skills and provides:
- Full plugin lifecycle guidance
- Security and quality audits
- Best practices enforcement
- Domain-specific patterns