Skip to content

Commit 58d51ee

Browse files
authored
Introduced webhook support (#31)
1 parent 974015a commit 58d51ee

File tree

99 files changed

+3415
-579
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+3415
-579
lines changed

.cursor/rules/general.mdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
description:
33
globs:
4-
alwaysApply: false
4+
alwaysApply: true
55
---
66
# Project overview
77

.github/workflows/docker.yaml

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,28 @@ jobs:
2020
- name: Set up Docker Buildx
2121
uses: docker/setup-buildx-action@v3
2222

23+
- name: Setup Bun
24+
uses: oven-sh/setup-bun@v2
25+
2326
- name: Login to GitHub Container Registry
2427
uses: docker/login-action@v3
2528
with:
2629
registry: ghcr.io
2730
username: ${{ github.repository_owner }}
2831
password: ${{ github.token }}
2932

30-
- name: Extract Docker metadata (Bun)
31-
id: meta-bun
32-
uses: docker/metadata-action@v5
33-
with:
34-
images: ghcr.io/dcodesdev/letterspace
35-
tags: |
36-
type=ref,event=tag
37-
type=semver,pattern={{version}}
38-
type=semver,pattern={{major}}.{{minor}}
39-
type=semver,pattern={{major}}
40-
type=raw,value=latest,enable=${{ !contains(github.ref, '-') }}
41-
type=raw,value=bun,enable=${{ !contains(github.ref, '-') }}
33+
- name: Generate Docker tags (Bun)
34+
id: tags-bun
35+
run: |
36+
TAGS=$(bun scripts/gen-container-img-tags.ts bun)
37+
echo "tags=$TAGS" >> $GITHUB_OUTPUT
4238
4339
- name: Build and push Docker image (Bun)
4440
uses: docker/build-push-action@v6
4541
with:
4642
context: .
4743
push: true
48-
tags: ${{ steps.meta-bun.outputs.tags }}
44+
tags: ${{ steps.tags-bun.outputs.tags }}
4945
# platforms: linux/amd64,linux/arm64
5046
cache-from: type=gha,scope=bun
5147
cache-to: type=gha,mode=max,scope=bun
@@ -63,34 +59,29 @@ jobs:
6359
- name: Set up Docker Buildx
6460
uses: docker/setup-buildx-action@v3
6561

62+
- name: Setup Bun
63+
uses: oven-sh/setup-bun@v2
64+
6665
- name: Login to GitHub Container Registry
6766
uses: docker/login-action@v3
6867
with:
6968
registry: ghcr.io
7069
username: ${{ github.repository_owner }}
7170
password: ${{ github.token }}
7271

73-
- name: Extract Docker metadata (Node)
74-
id: meta-node
75-
uses: docker/metadata-action@v5
76-
with:
77-
images: ghcr.io/dcodesdev/letterspace
78-
tags: |
79-
type=ref,event=tag,suffix=-node
80-
type=semver,pattern={{version}}-node
81-
type=semver,pattern={{major}}.{{minor}}-node
82-
type=semver,pattern={{major}}-node
83-
type=raw,value=latest-node,enable=${{ !contains(github.ref, '-') }}
84-
type=raw,value=node,enable=${{ !contains(github.ref, '-') }}
85-
type=raw,value=latest,enable=false
72+
- name: Generate Docker tags (Node)
73+
id: tags-node
74+
run: |
75+
TAGS=$(bun scripts/gen-container-img-tags.ts node)
76+
echo "tags=$TAGS" >> $GITHUB_OUTPUT
8677
8778
- name: Build and push Docker image (Node)
8879
uses: docker/build-push-action@v6
8980
with:
9081
context: .
9182
file: ./Dockerfile.node
9283
push: true
93-
tags: ${{ steps.meta-node.outputs.tags }}
84+
tags: ${{ steps.tags-node.outputs.tags }}
9485
# platforms: linux/amd64,linux/arm64
9586
cache-from: type=gha,scope=node
9687
cache-to: type=gha,mode=max,scope=node
@@ -107,3 +98,4 @@ jobs:
10798
uses: softprops/action-gh-release@v2
10899
with:
109100
body_path: RELEASE_NOTES.md
101+
prerelease: ${{ contains(github.ref_name, '-') }}

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ LetterSpace is an open source newsletter application that gives you complete con
2525
- TRPC
2626
- Prisma
2727

28+
## Environment Variables
29+
30+
### Required Variables
31+
32+
- `JWT_SECRET` - Secret key for JWT token signing
33+
- `DATABASE_URL` - PostgreSQL database connection string
34+
35+
### Optional Variables
36+
37+
- `WEBHOOK_MEMORY_LIMIT` - Memory limit for webhook transformer runtime in bytes (default: 16777216 = 16MB)
38+
- `WEBHOOK_MAX_STACK_SIZE` - Maximum stack size for webhook transformer in bytes (default: 262144 = 256KB)
39+
2840
## Getting Started
2941

3042
## Deployment

RELEASE_NOTES.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
### ✨ Features
22

3-
- Message status independence - retry individual messages regardless of campaign status
3+
- **Webhooks Support** - Receive real-time notifications for email events (delivered, opened, clicked, bounced, complained)
4+
- Custom webhook endpoints with authentication and transformation code support
5+
- Process email status updates from external email service providers
6+
- **Webhook Request Logging** - View detailed logs of all webhook requests with status codes, payloads, responses, and timing information
7+
- **Complained Message Status** - Track when recipients mark emails as spam
8+
- **Monaco Code Editor** - Enhanced code editing experience for webhook configuration
9+
- **Awaiting Webhook Status** - Track when messages are awaiting webhook processing
410

511
### 🐛 Bug Fixes
612

7-
- Fixed campaign creation targeting wrong subscribers (now filters by selected lists only)
8-
- Fixed campaign cancellation
13+
- Fixed unsubscribe functionality
914

1015
### 📚 Docs
1116

12-
See the latest documentation at [docs.letterspace.app](https://docs.letterspace.app).
17+
- Added comprehensive webhook documentation and event reference
18+
- See the latest documentation at [docs.letterspace.app](https://docs.letterspace.app).

apps/backend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"lint": "eslint .",
1111
"lint:fix": "eslint . --fix",
1212
"generate": "prisma generate",
13-
"generate:sql": "prisma generate --sql && pnpm exec prettier --write prisma/client",
13+
"generate:sql": "prisma generate --sql",
1414
"test": "dotenv -e .env.test -- vitest"
1515
},
1616
"exports": {
@@ -37,6 +37,7 @@
3737
"node-cron": "^3.0.3",
3838
"nodemailer": "^6.10.0",
3939
"p-map": "^7.0.3",
40+
"quickjs-emscripten": "^0.31.0",
4041
"superjson": "^2.2.2",
4142
"uuid": "^11.0.5",
4243
"zod": "^3.24.2"
Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,8 @@
11
export interface $DbEnums {}
22

3+
34
export namespace $DbEnums {
4-
type CampaignStatus =
5-
| "DRAFT"
6-
| "SCHEDULED"
7-
| "SENDING"
8-
| "COMPLETED"
9-
| "CANCELLED";
10-
type MessageStatus =
11-
| "QUEUED"
12-
| "PENDING"
13-
| "SENT"
14-
| "OPENED"
15-
| "CLICKED"
16-
| "FAILED"
17-
| "RETRYING";
18-
type SmtpEncryption = "STARTTLS" | "SSL_TLS" | "NONE";
5+
type CampaignStatus = "DRAFT" | "SCHEDULED" | "CREATING" | "SENDING" | "COMPLETED" | "CANCELLED"
6+
type MessageStatus = "QUEUED" | "PENDING" | "SENT" | "AWAITING_WEBHOOK" | "OPENED" | "CLICKED" | "FAILED" | "RETRYING" | "CANCELLED" | "COMPLAINED"
7+
type SmtpEncryption = "STARTTLS" | "SSL_TLS" | "NONE"
198
}
Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1-
import * as $runtime from "../runtime/library";
1+
import * as $runtime from "../runtime/library"
22

33
/**
44
* @param text
55
*/
6-
export const countDbSize: (
7-
text: string,
8-
) => $runtime.TypedSql<countDbSize.Parameters, countDbSize.Result>;
6+
export const countDbSize: (text: string) => $runtime.TypedSql<countDbSize.Parameters, countDbSize.Result>
97

108
export namespace countDbSize {
11-
export type Parameters = [text: string];
9+
export type Parameters = [text: string]
1210
export type Result = {
13-
organization_id: string;
14-
organization_name: string;
15-
campaign_count: bigint | null;
16-
template_count: bigint | null;
17-
message_count: bigint | null;
18-
subscriber_count: bigint | null;
19-
list_count: bigint | null;
20-
total_size_mb: $runtime.Decimal | null;
21-
};
11+
organization_id: string
12+
organization_name: string
13+
campaign_count: bigint | null
14+
template_count: bigint | null
15+
message_count: bigint | null
16+
subscriber_count: bigint | null
17+
list_count: bigint | null
18+
webhook_log_count: bigint | null
19+
total_size_mb: $runtime.Decimal | null
20+
}
2221
}

apps/backend/prisma/client/sql/countDbSize.edge.js

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)