Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Learned patterns #395

Merged
merged 24 commits into from
Apr 8, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .cursor/rules/gmail-api.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
description: Guidelines for working with Gmail API
globs:
alwaysApply: false
---
# Gmail API Usage

Guidelines for working with email provider APIs (Gmail, Outlook, etc.) to ensure maintainability and future provider support.
Currently we only support Gmail.

## Core Principles

1. **Never call provider APIs directly from routes or components**
2. **Always use wrapper functions from the utils folder**
3. **Keep provider-specific implementation details isolated**

## Directory Structure

```
apps/web/utils/
├── gmail/ # Gmail-specific implementations
│ ├── message.ts # Message operations (get, list, batch, etc.)
│ ├── thread.ts # Thread operations
│ ├── label.ts # Label operations
│ └── ...
├── outlook/ # Future Outlook implementation
└── ... # Other providers
```

## Usage Patterns

### ✅ DO: Use the abstraction layers

```typescript
// GOOD: Using provided utility functions
import { getMessages, getMessage } from "@/utils/gmail/message";

async function fetchEmails(gmail: gmail_v1.Gmail, query: string) {
// Use the wrapper function that handles implementation details
const messages = await getMessages(gmail, {
query,
maxResults: 10,
});

return messages;
}
```

### ❌ DON'T: Call provider APIs directly

```typescript
// BAD: Direct API calls
async function fetchEmails(gmail: gmail_v1.Gmail, query: string) {
// Direct API calls make future provider support difficult
const response = await gmail.users.messages.list({
userId: "me",
q: query,
maxResults: 10,
});

return response.data;
}
```

## Why This Matters

1. **Future Provider Support**: By isolating provider-specific implementations, we can add support for Outlook, ProtonMail, etc.
4 changes: 2 additions & 2 deletions .cursor/rules/llm-test.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ Tests for LLM-related functionality should follow these guidelines to ensure con
// Skip tests unless explicitly running AI tests
const isAiTest = process.env.RUN_AI_TESTS === "true";

describe.skipIf(!isAiTest)("yourFunction", () => {
describe.runIf(isAiTest)("yourFunction", () => {
beforeEach(() => {
vi.clearAllMocks();
});

test("test case description", async () => {
// Test implementation
});
});
}, 15_000);
```

## Helper Functions
Expand Down
2 changes: 1 addition & 1 deletion apps/web/__tests__/ai-categorize-senders.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const testSenders = [
},
];

describe.skipIf(!isAiTest)("AI Sender Categorization", () => {
describe.runIf(isAiTest)("AI Sender Categorization", () => {
describe("Bulk Categorization", () => {
it("should categorize senders with snippets using AI", async () => {
const result = await aiCategorizeSenders({
Expand Down
2 changes: 1 addition & 1 deletion apps/web/__tests__/ai-choose-args.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const isAiTest = process.env.RUN_AI_TESTS === "true";

vi.mock("server-only", () => ({}));

describe.skipIf(!isAiTest)("getActionItemsWithAiArgs", () => {
describe.runIf(isAiTest)("getActionItemsWithAiArgs", () => {
test("should return actions unchanged when no AI args needed", async () => {
const actions = [getAction({})];
const rule = getRule("Test rule", actions);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/__tests__/ai-choose-rule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const isAiTest = process.env.RUN_AI_TESTS === "true";

vi.mock("server-only", () => ({}));

describe.skipIf(!isAiTest)("aiChooseRule", () => {
describe.runIf(isAiTest)("aiChooseRule", () => {
test("Should return no rule when no rules passed", async () => {
const result = await aiChooseRule({
rules: [],
Expand Down
2 changes: 1 addition & 1 deletion apps/web/__tests__/ai-create-group.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ vi.mock("@/utils/gmail/message", () => ({
queryBatchMessages: vi.fn(),
}));

describe.skipIf(!isAiTest)("aiGenerateGroupItems", () => {
describe.runIf(isAiTest)("aiGenerateGroupItems", () => {
it("should generate group items based on user prompt", async () => {
const user = {
email: "[email protected]",
Expand Down
Loading