remove PRD and task list documents from PR

This commit is contained in:
Claude
2025-11-09 13:42:08 +00:00
parent a842808464
commit 3befa43a9e
2 changed files with 0 additions and 319 deletions

View File

@@ -1,249 +0,0 @@
# Product Requirements Document: Plunk Email Driver
## Introduction/Overview
This document outlines the requirements for implementing a new email driver for Plunk (https://useplunk.com) within the bknd framework. Plunk is an open-source email platform that provides a simple API for sending transactional emails. This driver will integrate Plunk's email service into bknd's existing driver ecosystem, allowing developers to send emails through Plunk using the same interface as other email providers (Resend, AWS SES, Mailchannels).
**Problem Statement:** bknd currently lacks support for Plunk as an email provider. Plunk offers a straightforward API and open-source platform that may be preferable for certain use cases.
**Goal:** Create a Plunk email driver that seamlessly integrates with bknd's existing `IEmailDriver` interface while supporting Plunk's specific features and limitations.
## Goals
1. Implement a fully functional Plunk email driver that adheres to bknd's `IEmailDriver` interface
2. Support single and multiple recipients (up to Plunk's 5-recipient limit)
3. Support common email features: custom sender (from), reply-to, sender name, and custom headers
4. Provide clear error handling and meaningful error messages
5. Include comprehensive unit tests following existing driver test patterns
6. Maintain consistency with existing email driver implementations (Resend, SES, Mailchannels)
## User Stories
1. **As a developer**, I want to configure Plunk as my email provider by passing my API key and optional configuration, so I can send emails through Plunk in my bknd application.
2. **As a developer**, I want to send emails to single or multiple recipients using the same interface, so I can easily switch between sending individual and bulk emails.
3. **As a developer**, I want to customize the sender name, email, and reply-to address, so I can control how my emails appear to recipients.
4. **As a developer**, I want to send HTML emails with automatic handling, so I don't have to worry about format conversion.
5. **As a developer**, I want clear error messages when email sending fails, so I can debug issues quickly.
## Functional Requirements
### 1. Driver Implementation
**FR-1.1:** The driver MUST be implemented as a factory function named `plunkEmail()` that accepts a configuration object and returns an `IEmailDriver` instance.
**FR-1.2:** The driver MUST implement the `IEmailDriver<PlunkEmailResponse, PlunkEmailSendOptions>` interface.
**FR-1.3:** The factory function MUST be exported from `/home/user/bknd/app/src/core/drivers/email/plunk.ts`.
**FR-1.4:** The driver MUST be re-exported from `/home/user/bknd/app/src/core/drivers/index.ts`.
### 2. Configuration
**FR-2.1:** The driver MUST accept a configuration object with the following type:
```typescript
type PlunkEmailOptions = {
apiKey: string; // Required: Plunk API key
host?: string; // Optional: API endpoint (default: "https://api.useplunk.com/v1/send")
from?: string; // Optional: Default sender email
}
```
**FR-2.2:** If `host` is not provided, the driver MUST default to `"https://api.useplunk.com/v1/send"`.
**FR-2.3:** If `from` is not provided in the config or send options, the driver MUST allow Plunk to use its default (verified email).
### 3. Send Method
**FR-3.1:** The `send()` method MUST accept the following parameters:
- `to: string` - Recipient email address (required)
- `subject: string` - Email subject (required)
- `body: string | { text: string; html: string }` - Email body (required)
- `options?: PlunkEmailSendOptions` - Additional send options (optional)
**FR-3.2:** When `body` is a string, it MUST be sent as-is to Plunk's `body` field.
**FR-3.3:** When `body` is an object with `{ text, html }`, the driver MUST send the `html` value to Plunk's `body` field (Plunk only supports a single body field).
**FR-3.4:** The method MUST return a `Promise<PlunkEmailResponse>`.
### 4. Send Options
**FR-4.1:** The driver MUST support the following send options:
```typescript
type PlunkEmailSendOptions = {
to?: string | string[]; // Additional recipient(s) - overrides/extends main to parameter
subscribed?: boolean; // Add contact to audience (default: false)
name?: string; // Override sender name
from?: string; // Override sender email
reply?: string; // Reply-to address
headers?: Record<string, string>; // Custom email headers
}
```
**FR-4.2:** If `options.to` is provided, it MUST override the main `to` parameter when constructing the API request.
**FR-4.3:** If `options.to` is a string, it MUST be converted to a single-element array for the API request.
**FR-4.4:** If `options.to` is an array, it MUST be validated to ensure it doesn't exceed 5 recipients (Plunk's limit).
**FR-4.5:** If `options.from` is provided, it MUST override the default `from` from configuration.
### 5. Response Handling
**FR-5.1:** The driver MUST define a response type matching Plunk's API response:
```typescript
type PlunkEmailResponse = {
success: boolean;
emails: Array<{
contact: {
id: string;
email: string;
};
email: string; // Email ID
}>;
timestamp: string;
}
```
**FR-5.2:** On successful API response (`res.ok === true`), the driver MUST parse and return the JSON response as `PlunkEmailResponse`.
**FR-5.3:** On failed API response (`res.ok === false`), the driver MUST throw an error with the response text.
### 6. HTTP Request
**FR-6.1:** The driver MUST use the `fetch()` API to make HTTP requests.
**FR-6.2:** The request MUST use the POST method.
**FR-6.3:** The request MUST include the following headers:
- `Content-Type: application/json`
- `Authorization: Bearer ${apiKey}`
**FR-6.4:** The request body MUST be a JSON-stringified object containing:
- Required: `to`, `subject`, `body`
- Optional: `subscribed`, `name`, `from`, `reply`, `headers` (when provided in options)
**FR-6.5:** When merging the payload with options, options MUST be spread after the base payload to allow overrides.
### 7. Testing
**FR-7.1:** Unit tests MUST be created in `/home/user/bknd/app/src/core/drivers/email/plunk.spec.ts`.
**FR-7.2:** Tests MUST follow the pattern established in `resend.spec.ts` (using `describe.skipIf(ALL_TESTS)`).
**FR-7.3:** Tests MUST include:
- Test for invalid API key (should throw error)
- Test for successful email send with valid credentials (requires `PLUNK_API_KEY` environment variable)
- Test for HTML email body
- Test for `{ text, html }` body object
- Test for multiple recipients
**FR-7.4:** Tests MUST use Bun's test framework (`bun:test`).
## Non-Goals (Out of Scope)
1. **File Attachments:** The initial implementation will NOT support file attachments. Plunk supports up to 5 attachments, but this will be deferred to a future iteration.
2. **CC/BCC Support:** Plunk's API does not support CC or BCC functionality. This will NOT be implemented.
3. **Template Support:** Plunk may support email templates, but this driver will only support direct body content. Template support is out of scope.
4. **Delayed/Scheduled Sending:** While Plunk may support scheduled emails, this is out of scope for the initial implementation.
5. **Email Tracking/Analytics:** Any tracking or analytics features are out of scope.
6. **Batch Sending:** While Plunk supports up to 5 recipients per call, this driver will not implement special batch optimization logic.
## Design Considerations
### File Structure
```
/home/user/bknd/app/src/core/drivers/email/
├── plunk.ts # Main driver implementation
├── plunk.spec.ts # Unit tests
└── index.ts # Updated to export types (if needed)
```
### Code Pattern
The implementation should closely follow the pattern established in `resend.ts`:
- Factory function returning an object with `send()` method
- Configuration stored in closure
- Use of `fetch()` for HTTP requests
- Error handling via `res.ok` check and thrown errors
- Proper TypeScript typing throughout
### Integration
The driver must be exported from `/home/user/bknd/app/src/core/drivers/index.ts`:
```typescript
export { plunkEmail } from "./email/plunk";
```
## Technical Considerations
### Dependencies
- No additional npm packages required (uses built-in `fetch()`)
- Uses existing `IEmailDriver` interface
### API Endpoint
- Base URL: `https://api.useplunk.com/v1/send`
- Method: POST
- Authentication: Bearer token in Authorization header
### Recipient Limit
Plunk enforces a maximum of 5 recipients per API call. The driver should validate this:
```typescript
const recipients = Array.isArray(options?.to) ? options.to :
options?.to ? [options.to] : [to];
if (recipients.length > 5) {
throw new Error("Plunk supports a maximum of 5 recipients per email");
}
```
### Body Field Handling
Since Plunk only accepts a single `body` field (not separate text/html):
- When `body` is a string → send as-is
- When `body` is `{ text, html }` → send `html` value (HTML emails degrade gracefully in most clients)
### Error Messages
Follow the pattern from other drivers:
```typescript
if (!res.ok) {
throw new Error(`Plunk API error: ${await res.text()}`);
}
```
## Success Metrics
1. **Implementation Completeness:** All functional requirements are met and tested
2. **Test Coverage:** All critical paths have unit test coverage
3. **API Compatibility:** Successfully sends emails through Plunk API with 100% success rate in tests
4. **Code Quality:** Passes existing linting and formatting standards
5. **Documentation:** Code is well-commented and follows existing patterns
## Open Questions
1. **Environment Variable:** Should we follow the same pattern as Resend and expect `PLUNK_API_KEY` in environment variables for testing?
- **Answer:** Yes, follow existing pattern
2. **Error Response Format:** What is the exact structure of Plunk's error responses? Should we parse JSON errors or use raw text?
- **Action:** Test with invalid API key to determine error format
3. **Name Field Priority:** When both `config.from` and `options.name` are provided, which should take precedence for the sender name?
- **Answer:** `options.name` should override (same pattern as other drivers)
4. **Multiple Recipients in Main Parameter:** Should we support passing an array to the main `to` parameter via the interface, or strictly enforce single string?
- **Answer:** The interface signature is `to: string`, so arrays must go through `options.to`
5. **Headers Validation:** Does Plunk have restrictions on custom headers? Should we validate or just pass through?
- **Answer:** Pass through - let Plunk API handle validation
---
**Document Version:** 1.0
**Created:** 2025-11-09
**Target Audience:** Junior to mid-level developers
**Estimated Implementation Time:** 2-4 hours

View File

@@ -1,70 +0,0 @@
## Relevant Files
- `/home/user/bknd/app/src/core/drivers/email/plunk.ts` - Main Plunk email driver implementation
- `/home/user/bknd/app/src/core/drivers/email/plunk.spec.ts` - Unit tests for Plunk email driver
- `/home/user/bknd/app/src/core/drivers/email/index.ts` - Email driver interface definition (reference)
- `/home/user/bknd/app/src/core/drivers/index.ts` - Main drivers export file (needs update to export plunkEmail)
- `/home/user/bknd/app/src/core/drivers/email/resend.ts` - Reference implementation to follow same pattern
### Notes
- Follow the same factory pattern used in `resend.ts` for consistency
- Use Bun's test framework (`bun:test`) for unit tests
- Tests require `PLUNK_API_KEY` environment variable for integration tests
- Plunk API endpoint: `https://api.useplunk.com/v1/send`
- Maximum 5 recipients per email (Plunk API limitation)
- Run tests with: `bun test app/src/core/drivers/email/plunk.spec.ts`
## Instructions for Completing Tasks
**IMPORTANT:** As you complete each task, you must check it off in this markdown file by changing `- [ ]` to `- [x]`. This helps track progress and ensures you don't skip any steps.
Example:
- `- [ ] 1.1 Read file``- [x] 1.1 Read file` (after completing)
Update the file after completing each sub-task, not just after completing an entire parent task.
## Tasks
- [x] 0.0 Create feature branch
- [x] 0.1 Verify current branch (already on `claude/add-loops-email-driver-011CUxMpVqe8AT22gN2k5ZVm`)
- [x] 1.0 Implement Plunk email driver
- [x] 1.1 Read `resend.ts` file to understand the factory pattern and implementation structure
- [x] 1.2 Create `/home/user/bknd/app/src/core/drivers/email/plunk.ts` file
- [x] 1.3 Define `PlunkEmailOptions` type with `apiKey`, `host?`, and `from?` fields
- [x] 1.4 Define `PlunkEmailSendOptions` type with `to?`, `subscribed?`, `name?`, `from?`, `reply?`, and `headers?` fields
- [x] 1.5 Define `PlunkEmailResponse` type matching Plunk's API response structure (`success`, `emails`, `timestamp`)
- [x] 1.6 Implement `plunkEmail()` factory function that accepts config and returns `IEmailDriver` instance
- [x] 1.7 Implement `send()` method with proper body handling (string vs `{ text, html }` object)
- [x] 1.8 Add recipient validation to ensure max 5 recipients when `options.to` is an array
- [x] 1.9 Add HTTP request implementation using `fetch()` with proper headers (Authorization, Content-Type)
- [x] 1.10 Add error handling for failed API responses (check `res.ok` and throw with error text)
- [x] 1.11 Implement proper payload construction with `to`, `subject`, `body`, and optional fields
- [x] 2.0 Create unit tests for Plunk driver
- [x] 2.1 Read `resend.spec.ts` to understand test pattern and structure
- [x] 2.2 Create `/home/user/bknd/app/src/core/drivers/email/plunk.spec.ts` file
- [x] 2.3 Set up test structure with `describe.skipIf(ALL_TESTS)` wrapper
- [x] 2.4 Write test: "should throw on failed" - test with invalid API key expecting error
- [x] 2.5 Write test: "should send an email" - test successful email send (requires `PLUNK_API_KEY` env var)
- [x] 2.6 Write test: "should send HTML email" - test with HTML string body
- [x] 2.7 Write test: "should send with text and html" - test with `{ text, html }` body object
- [x] 2.8 Write test: "should send to multiple recipients" - test with array of recipients in options
- [x] 3.0 Update driver exports
- [x] 3.1 Read current `/home/user/bknd/app/src/core/drivers/index.ts` file
- [x] 3.2 Add `export { plunkEmail } from "./email/plunk";` to `/home/user/bknd/app/src/core/drivers/index.ts`
- [x] 4.0 Verify implementation and run tests
- [x] 4.1 Run Plunk driver tests with `bun test app/src/core/drivers/email/plunk.spec.ts`
- [x] 4.2 Verify all tests pass (or only skip if `ALL_TESTS` is true and no `PLUNK_API_KEY`)
- [x] 4.3 Review code for consistency with existing drivers (resend.ts pattern)
- [x] 4.4 Verify TypeScript types are correctly defined and exported
- [x] 5.0 Commit and push changes
- [x] 5.1 Stage all changed files (`plunk.ts`, `plunk.spec.ts`, `index.ts`)
- [x] 5.2 Review git diff to ensure changes are correct
- [x] 5.3 Create descriptive commit message following repository convention
- [x] 5.4 Commit changes with proper message
- [x] 5.5 Push to remote branch `claude/add-loops-email-driver-011CUxMpVqe8AT22gN2k5ZVm`