Back to list
encoredev

encore-code-review

by encoredev

Agent Skills for development with Encore.

10🍴 1📅 Jan 23, 2026

SKILL.md


name: encore-code-review description: Review Encore.ts code for best practices and anti-patterns.

Encore Code Review

Instructions

When reviewing Encore.ts code, check for these common issues:

Critical Issues

1. Infrastructure Inside Functions

// WRONG: Infrastructure declared inside function
async function setup() {
  const db = new SQLDatabase("mydb", { migrations: "./migrations" });
  const topic = new Topic<Event>("events", { deliveryGuarantee: "at-least-once" });
}

// CORRECT: Package level declaration
const db = new SQLDatabase("mydb", { migrations: "./migrations" });
const topic = new Topic<Event>("events", { deliveryGuarantee: "at-least-once" });

2. Using require() Instead of import

// WRONG
const { api } = require("encore.dev/api");

// CORRECT
import { api } from "encore.dev/api";

3. Wrong Service Import Pattern

// WRONG: Direct import from another service
import { getUser } from "../user/api";

// CORRECT: Use ~encore/clients
import { user } from "~encore/clients";
const result = await user.getUser({ id });

4. Missing Error Handling

// WRONG: Returning null for not found
const user = await db.queryRow`SELECT * FROM users WHERE id = ${id}`;
if (!user) return null;

// CORRECT: Throw APIError
import { APIError } from "encore.dev/api";

const user = await db.queryRow`SELECT * FROM users WHERE id = ${id}`;
if (!user) {
  throw APIError.notFound("user not found");
}

5. SQL Injection Risk

// WRONG: String concatenation
await db.query(`SELECT * FROM users WHERE email = '${email}'`);

// CORRECT: Template literal with automatic escaping
await db.queryRow`SELECT * FROM users WHERE email = ${email}`;

Warning Issues

6. Missing Type Annotations

// WEAK: No explicit types
export const getUser = api(
  { method: "GET", path: "/users/:id", expose: true },
  async ({ id }) => {
    return await findUser(id);
  }
);

// BETTER: Explicit request/response types
interface GetUserRequest { id: string; }
interface User { id: string; email: string; name: string; }

export const getUser = api(
  { method: "GET", path: "/users/:id", expose: true },
  async ({ id }: GetUserRequest): Promise<User> => {
    return await findUser(id);
  }
);

7. Exposed Internal Endpoints

// CHECK: Should this cron endpoint be exposed?
export const cleanupJob = api(
  { expose: true },  // Probably should be false
  async () => { /* ... */ }
);

8. Non-Idempotent Subscription Handlers

// RISKY: Not idempotent (pubsub has at-least-once delivery)
const _ = new Subscription(orderCreated, "process-order", {
  handler: async (event) => {
    await chargeCustomer(event.orderId);  // Could charge twice!
  },
});

// SAFER: Check before processing
const _ = new Subscription(orderCreated, "process-order", {
  handler: async (event) => {
    const order = await getOrder(event.orderId);
    if (order.status !== "pending") return;  // Already processed
    await chargeCustomer(event.orderId);
  },
});

9. Secrets Called at Module Level

// WRONG: Secret accessed at startup
const stripeKey = secret("StripeKey");
const client = new Stripe(stripeKey());  // Called during import

// CORRECT: Access inside functions
const stripeKey = secret("StripeKey");

async function charge() {
  const client = new Stripe(stripeKey());  // Called at runtime
}

Review Checklist

  • All infrastructure at package level
  • Using ES6 imports, not require()
  • Cross-service calls use ~encore/clients
  • Proper error handling with APIError
  • SQL uses template literals
  • Request/response types defined
  • Internal endpoints have expose: false
  • Subscription handlers are idempotent
  • Secrets accessed inside functions, not at import time
  • Migrations follow naming convention (001_name.up.sql)

Output Format

When reviewing, report issues as:

[CRITICAL] [file:line] Description of issue
[WARNING] [file:line] Description of concern  
[GOOD] Notable good practice observed

Score

Total Score

60/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

0/5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon