vendure-graphql-reviewing

📁 meriley/claude-code-skills 📅 14 days ago
1
总安装量
1
周安装量
#44791
全站排名
安装命令
npx skills add https://github.com/meriley/claude-code-skills --skill vendure-graphql-reviewing

Agent 安装分布

pi 1
opencode 1
cursor 1
codex 1
claude-code 1
gemini-cli 1

Skill 文档

Vendure GraphQL Reviewing

Purpose

Audit Vendure GraphQL resolvers and schema extensions for violations and anti-patterns.

Review Workflow

Step 1: Identify GraphQL Files

# Find resolver files
find . -name "*.resolver.ts"

# Find schema files
find . -name "schema.ts" -o -name "*.graphql"

Step 2: Run Automated Checks

# === CRITICAL VIOLATIONS ===

# Missing @Ctx() RequestContext
grep -rn "@Query\|@Mutation" --include="*.resolver.ts" -A 5 | grep -v "@Ctx()"

# Missing @Resolver decorator
grep -rn "export class.*Resolver" --include="*.resolver.ts" | grep -v "@Resolver"

# Missing @Allow permissions
grep -rn "@Query\|@Mutation" --include="*.resolver.ts" -A 3 | grep -v "@Allow"

# === HIGH PRIORITY ===

# Direct entity returns (should use DTOs or proper types)
grep -rn "Promise<.*Entity>" --include="*.resolver.ts"

# Missing @Transaction on mutations
grep -rn "@Mutation" --include="*.resolver.ts" -A 2 | grep -v "@Transaction"

# InputMaybe not handled correctly
grep -rn "!== undefined" --include="*.service.ts" | grep -v "&& .* !== null"

# === MEDIUM PRIORITY ===

# Hardcoded permission strings
grep -rn "@Allow(['\"]" --include="*.resolver.ts"

# Missing error handling
grep -rn "async.*@Ctx" --include="*.resolver.ts" -A 10 | grep -v "throw\|catch\|try"

Step 3: Manual Review Checklist

Schema

  • Uses gql template literal
  • Input types for all mutations
  • Proper type definitions
  • Admin vs Shop separation clear
  • No sensitive fields in Shop API

Resolvers

  • @Resolver() decorator present
  • @Ctx() ctx: RequestContext on all methods
  • @Allow() with appropriate permissions
  • @Transaction() on mutations
  • Service injection (not direct DB access)

Security

  • Shop API doesn’t expose admin data
  • Owner permission checked for user resources
  • Input validation present
  • Error messages don’t leak sensitive info

Severity Classification

CRITICAL (Must Fix)

  • Missing RequestContext parameter
  • No permission decorators
  • Shop API exposes admin data
  • Direct database access in resolvers

HIGH (Should Fix)

  • Missing @Transaction on mutations
  • InputMaybe not handled correctly
  • No error handling
  • Entity types returned directly

MEDIUM (Should Fix)

  • Missing input validation
  • Poor error messages
  • Inconsistent naming

Common Violations

1. Missing RequestContext

Violation:

@Query()
@Allow(Permission.ReadSettings)
async myQuery(): Promise<MyEntity[]> {  // No ctx!
  return this.service.findAll();
}

Fix:

@Query()
@Allow(Permission.ReadSettings)
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
  return this.service.findAll(ctx);
}

2. Missing Permission Decorator

Violation:

@Query()
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
  // No @Allow - anyone can call this!
  return this.service.findAll(ctx);
}

Fix:

@Query()
@Allow(Permission.ReadSettings)  // Explicit permission
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
  return this.service.findAll(ctx);
}

3. InputMaybe Bug

Violation:

// Only checks undefined, null passes through!
if (input.name !== undefined) {
  entity.name = input.name;
}

Fix:

// Check both undefined AND null
if (input.name !== undefined && input.name !== null) {
  entity.name = input.name;
}

4. Missing Transaction

Violation:

@Mutation()
@Allow(Permission.UpdateSettings)
async updateData(@Ctx() ctx: RequestContext, @Args() args): Promise<MyEntity> {
  // No @Transaction - partial updates possible on error!
  await this.service.updateA(ctx, args);
  await this.service.updateB(ctx, args);  // If this fails, A is updated
}

Fix:

@Mutation()
@Transaction()  // Atomic operation
@Allow(Permission.UpdateSettings)
async updateData(@Ctx() ctx: RequestContext, @Args() args): Promise<MyEntity> {
  await this.service.updateA(ctx, args);
  await this.service.updateB(ctx, args);
}

5. Shop API Leaking Admin Data

Violation:

// Shop schema
const shopSchema = gql`
  type User {
    id: ID!
    email: String!
    internalNotes: String! # Admin-only field exposed!
  }
`;

Fix:

// Shop schema - limited fields
const shopSchema = gql`
  type User {
    id: ID!
    email: String!
    # internalNotes excluded
  }
`;

Quick Detection Commands

# All-in-one GraphQL audit
echo "=== CRITICAL: Missing @Ctx ===" && \
grep -rn "@Query\|@Mutation" --include="*.resolver.ts" -A 5 | grep -v "@Ctx" | head -20 && \
echo "" && \
echo "=== HIGH: Missing @Allow ===" && \
grep -rn "@Query\|@Mutation" --include="*.resolver.ts" -A 3 | grep -v "@Allow" | head -20 && \
echo "" && \
echo "=== MEDIUM: InputMaybe issues ===" && \
grep -rn "!== undefined" --include="*.ts" | grep -v "&& .* !== null" | head -20

Review Output Template

## GraphQL Review: [Component Name]

### Summary

[Overview of GraphQL code quality]

### Critical Issues (Must Fix)

- [ ] [Issue] - `file:line`

### High Priority

- [ ] [Issue] - `file:line`

### Passed Checks

- [x] All resolvers have @Resolver decorator
- [x] RequestContext passed consistently
- [x] Permissions declared

### Recommendations

- [Suggestions]

Cross-Reference

All rules match patterns in vendure-graphql-writing skill.


Related Skills

  • vendure-graphql-writing – GraphQL patterns
  • vendure-plugin-reviewing – Plugin-level review