hookdash 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 hookdash contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,385 @@
1
+ <div align="center">
2
+
3
+ # ∿ hookdash
4
+
5
+ **Zero-config, self-hosted webhook gateway with a beautiful dashboard.**
6
+
7
+ Receive, queue, retry, and monitor webhooks — no Redis, no Postgres, just SQLite.
8
+
9
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
10
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
12
+
13
+ [Quick Start](#-quick-start) · [Configuration](#-configuration) · [Dashboard](#-dashboard) · [API](#-api-reference) · [Docker](#-docker) · [Contributing](#-contributing)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## Why hookdash?
20
+
21
+ Every app that integrates with Stripe, GitHub, Twilio, or Shopify needs to handle webhooks. But webhooks are fragile — your server goes down, you lose events. You need retry logic, signature verification, monitoring, and replay capabilities.
22
+
23
+ **hookdash** gives you all of that in a single command:
24
+
25
+ ```bash
26
+ npx hookdash start
27
+ ```
28
+
29
+ No Redis. No Postgres. No Kafka. Just a single SQLite file and a beautiful dashboard.
30
+
31
+ ### How it compares
32
+
33
+ | Feature | hookdash | Svix | Convoy | Hookdeck |
34
+ |---|---|---|---|---|
35
+ | Zero external deps | ✅ SQLite only | ❌ PG + Redis + Kafka | ❌ PG + Redis | ❌ Cloud only |
36
+ | Setup time | `npx hookdash` | Hours | Hours | Minutes |
37
+ | Self-hosted | ✅ | ✅ | ✅ | ❌ |
38
+ | Dashboard | ✅ Beautiful | ✅ | ✅ | ✅ |
39
+ | Signature verification | ✅ Multi-provider | ✅ | ✅ | ✅ |
40
+ | License | MIT | MIT (server) | Varies | Proprietary |
41
+ | Target audience | Devs & small teams | Enterprise | Enterprise | Everyone |
42
+
43
+ ---
44
+
45
+ ## ✨ Features
46
+
47
+ - 🪝 **Webhook Ingestion** — Receive webhooks from any service at `/webhook/:source`
48
+ - 🔐 **Signature Verification** — Built-in support for Stripe, GitHub, Twilio, Shopify, and generic HMAC
49
+ - 🔄 **Smart Retries** — Exponential backoff with jitter, configurable per-endpoint
50
+ - ⚡ **Circuit Breaker** — Auto-disable failing endpoints, probe for recovery
51
+ - 💀 **Dead Letter Queue** — Events that exceed retries are preserved for inspection
52
+ - 🔁 **One-Click Replay** — Re-deliver any failed event from the dashboard
53
+ - 📊 **Real-time Dashboard** — Beautiful dark UI with live event stream
54
+ - 📡 **Server-Sent Events** — Real-time updates without WebSocket complexity
55
+ - 🗄️ **SQLite Storage** — Zero-config, single file, fast, reliable
56
+ - 🐳 **Docker Ready** — Single container deployment
57
+ - ⚙️ **YAML Config** — Simple configuration with environment variable interpolation
58
+
59
+ ---
60
+
61
+ ## 🚀 Quick Start
62
+
63
+ ### Option 1: npx (quickest)
64
+
65
+ ```bash
66
+ # Create a config file
67
+ npx hookdash init
68
+
69
+ # Edit hookdash.config.yml with your settings, then:
70
+ npx hookdash start
71
+ ```
72
+
73
+ ### Option 2: Install globally
74
+
75
+ ```bash
76
+ npm install -g hookdash
77
+ hookdash init
78
+ hookdash start
79
+ ```
80
+
81
+ ### Option 3: Docker
82
+
83
+ ```bash
84
+ docker run -p 9090:9090 -v hookdash-data:/app/data hookdash/hookdash
85
+ ```
86
+
87
+ ### Test it works
88
+
89
+ ```bash
90
+ # Send a test webhook
91
+ curl -X POST http://localhost:9090/webhook/my-service \
92
+ -H "Content-Type: application/json" \
93
+ -d '{"event": "test.event", "data": {"hello": "world"}}'
94
+
95
+ # Open the dashboard
96
+ open http://localhost:9090
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 📋 Configuration
102
+
103
+ Create a `hookdash.config.yml` in your project root:
104
+
105
+ ```yaml
106
+ server:
107
+ port: 9090
108
+ host: 0.0.0.0
109
+
110
+ database:
111
+ path: ./hookdash.db
112
+
113
+ delivery:
114
+ poll_interval: 1000 # ms between delivery polls
115
+ default_timeout: 30000 # ms per delivery attempt
116
+ default_max_retries: 8 # retries before dead letter
117
+
118
+ sources:
119
+ # Stripe
120
+ - name: stripe
121
+ provider: stripe
122
+ signing_secret: ${STRIPE_WEBHOOK_SECRET}
123
+ endpoints:
124
+ - url: http://localhost:3000/api/webhooks/stripe
125
+ events: ["payment_intent.*", "charge.*"]
126
+
127
+ # GitHub
128
+ - name: github
129
+ provider: github
130
+ signing_secret: ${GITHUB_WEBHOOK_SECRET}
131
+ endpoints:
132
+ - url: http://localhost:3000/api/webhooks/github
133
+
134
+ # Generic HMAC-SHA256
135
+ - name: my-service
136
+ provider: generic
137
+ signing_secret: my-secret-key
138
+ endpoints:
139
+ - url: http://localhost:3000/hooks
140
+ ```
141
+
142
+ ### Environment Variables
143
+
144
+ Use `${ENV_VAR}` syntax in your config to reference environment variables:
145
+
146
+ ```yaml
147
+ signing_secret: ${STRIPE_WEBHOOK_SECRET}
148
+ ```
149
+
150
+ ### CLI Options
151
+
152
+ ```bash
153
+ hookdash start [options]
154
+
155
+ Options:
156
+ -p, --port <port> Server port (overrides config)
157
+ -h, --host <host> Server host (overrides config)
158
+ -c, --config <path> Path to config file
159
+ -d, --db <path> Database file path
160
+ ```
161
+
162
+ ---
163
+
164
+ ## 📊 Dashboard
165
+
166
+ The dashboard is available at `http://localhost:9090` and provides:
167
+
168
+ - **Event Explorer** — Search and filter all incoming webhooks
169
+ - **Event Detail** — View full payload, headers, and delivery timeline
170
+ - **Replay** — One-click re-delivery of any event
171
+ - **Stats** — Success rates, event volume, top sources
172
+ - **Endpoint Manager** — Configure and test forwarding destinations
173
+ - **Real-time Updates** — Live event stream via SSE
174
+
175
+ ---
176
+
177
+ ## 📡 API Reference
178
+
179
+ All API endpoints are available at `/api/`.
180
+
181
+ ### Events
182
+
183
+ | Method | Endpoint | Description |
184
+ |---|---|---|
185
+ | `GET` | `/api/events` | List events (paginated) |
186
+ | `GET` | `/api/events/:id` | Event detail + deliveries |
187
+ | `POST` | `/api/events/:id/replay` | Replay an event |
188
+ | `DELETE` | `/api/events/:id` | Delete an event |
189
+
190
+ **Query parameters for `GET /api/events`:**
191
+
192
+ | Param | Type | Description |
193
+ |---|---|---|
194
+ | `page` | number | Page number (default: 1) |
195
+ | `per_page` | number | Items per page (default: 20, max: 100) |
196
+ | `source` | string | Filter by source name |
197
+ | `status` | string | Filter by delivery status |
198
+ | `event_type` | string | Filter by event type |
199
+ | `from` | string | ISO date, events after |
200
+ | `to` | string | ISO date, events before |
201
+ | `search` | string | Search in event body |
202
+
203
+ ### Endpoints
204
+
205
+ | Method | Endpoint | Description |
206
+ |---|---|---|
207
+ | `GET` | `/api/endpoints` | List endpoints |
208
+ | `POST` | `/api/endpoints` | Create endpoint |
209
+ | `PUT` | `/api/endpoints/:id` | Update endpoint |
210
+ | `DELETE` | `/api/endpoints/:id` | Delete endpoint |
211
+ | `POST` | `/api/endpoints/:id/test` | Test endpoint connectivity |
212
+
213
+ ### Stats & Health
214
+
215
+ | Method | Endpoint | Description |
216
+ |---|---|---|
217
+ | `GET` | `/api/stats` | Aggregate statistics |
218
+ | `GET` | `/api/stream` | SSE real-time event stream |
219
+ | `GET` | `/api/health` | Health check |
220
+
221
+ ---
222
+
223
+ ## 🪝 Webhook Providers
224
+
225
+ ### Stripe
226
+
227
+ ```yaml
228
+ - name: stripe
229
+ provider: stripe
230
+ signing_secret: ${STRIPE_WEBHOOK_SECRET}
231
+ ```
232
+
233
+ Verifies using the `Stripe-Signature` header with HMAC-SHA256. Validates timestamp tolerance (5 minutes).
234
+
235
+ ### GitHub
236
+
237
+ ```yaml
238
+ - name: github
239
+ provider: github
240
+ signing_secret: ${GITHUB_WEBHOOK_SECRET}
241
+ ```
242
+
243
+ Verifies using the `X-Hub-Signature-256` header with HMAC-SHA256.
244
+
245
+ ### Twilio
246
+
247
+ ```yaml
248
+ - name: twilio
249
+ provider: twilio
250
+ signing_secret: ${TWILIO_AUTH_TOKEN}
251
+ ```
252
+
253
+ Verifies using the `X-Twilio-Signature` header with HMAC-SHA1.
254
+
255
+ ### Shopify
256
+
257
+ ```yaml
258
+ - name: shopify
259
+ provider: shopify
260
+ signing_secret: ${SHOPIFY_WEBHOOK_SECRET}
261
+ ```
262
+
263
+ Verifies using the `X-Shopify-Hmac-Sha256` header with HMAC-SHA256 (Base64).
264
+
265
+ ### Generic HMAC
266
+
267
+ ```yaml
268
+ - name: my-service
269
+ provider: generic
270
+ signing_secret: my-secret-key
271
+ ```
272
+
273
+ Verifies using `X-Webhook-Signature` or `X-Signature` header with HMAC-SHA256.
274
+
275
+ ---
276
+
277
+ ## 🔄 Retry Strategy
278
+
279
+ hookdash uses **exponential backoff with jitter**:
280
+
281
+ | Attempt | Delay (approx) |
282
+ |---|---|
283
+ | 1 | ~1s |
284
+ | 2 | ~2s |
285
+ | 3 | ~4s |
286
+ | 4 | ~8s |
287
+ | 5 | ~16s |
288
+ | 6 | ~32s |
289
+ | 7 | ~1 min |
290
+ | 8 | ~2 min |
291
+
292
+ After the configured max retries (default: 8), the event moves to the **dead letter queue** and can be replayed manually from the dashboard.
293
+
294
+ ### Circuit Breaker
295
+
296
+ If an endpoint fails 5 times consecutively, hookdash **opens the circuit** and stops sending to that endpoint for 60 seconds. After the cooldown, it enters **half-open** state and probes with a single request.
297
+
298
+ ---
299
+
300
+ ## 🐳 Docker
301
+
302
+ ### Using Docker Compose
303
+
304
+ ```bash
305
+ # Clone the repo
306
+ git clone https://github.com/hookdash/hookdash.git
307
+ cd hookdash
308
+
309
+ # Create your config
310
+ cp hookdash.config.example.yml hookdash.config.yml
311
+
312
+ # Start
313
+ docker compose up -d
314
+ ```
315
+
316
+ ### Using Docker directly
317
+
318
+ ```bash
319
+ docker build -t hookdash .
320
+ docker run -p 9090:9090 -v hookdash-data:/app/data hookdash
321
+ ```
322
+
323
+ ---
324
+
325
+ ## 🛠 Development
326
+
327
+ ```bash
328
+ # Clone
329
+ git clone https://github.com/hookdash/hookdash.git
330
+ cd hookdash
331
+
332
+ # Install dependencies
333
+ npm install
334
+ cd dashboard && npm install && cd ..
335
+
336
+ # Start in dev mode (with hot reload)
337
+ npm run dev
338
+
339
+ # Run tests
340
+ npm test
341
+
342
+ # Build for production
343
+ npm run build
344
+ ```
345
+
346
+ ---
347
+
348
+ ## 🗺 Roadmap
349
+
350
+ - [ ] Web UI for creating sources (no YAML editing)
351
+ - [ ] Webhook forwarding transforms (modify payload before delivery)
352
+ - [ ] Rate limiting per source
353
+ - [ ] Authentication for dashboard (API key / basic auth)
354
+ - [ ] Metrics export (Prometheus)
355
+ - [ ] Webhook playground (send test events from dashboard)
356
+ - [ ] Plugin system for custom providers
357
+ - [ ] PostgreSQL adapter for high-volume deployments
358
+
359
+ ---
360
+
361
+ ## 🤝 Contributing
362
+
363
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
364
+
365
+ 1. Fork the repository
366
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
367
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
368
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
369
+ 5. Open a Pull Request
370
+
371
+ ---
372
+
373
+ ## 📄 License
374
+
375
+ MIT — see [LICENSE](LICENSE) for details.
376
+
377
+ ---
378
+
379
+ <div align="center">
380
+
381
+ **Built with ❤️ for developers who are tired of losing webhooks.**
382
+
383
+ [⭐ Star on GitHub](https://github.com/hookdash/hookdash) · [🐛 Report Bug](https://github.com/hookdash/hookdash/issues) · [💡 Request Feature](https://github.com/hookdash/hookdash/issues)
384
+
385
+ </div>
@@ -0,0 +1 @@
1
+ :root{--bg-color: #08080c;--card-bg: #11111a;--border-color: #1e1e2d;--text-primary: #f3f4f6;--text-secondary: #9ca3af;--text-muted: #6b7280;--accent-color: #3b82f6;--accent-glow: rgba(59, 130, 246, .15);--success-color: #10b981;--success-glow: rgba(16, 185, 129, .1);--warning-color: #f59e0b;--error-color: #ef4444;--dead-color: #4b5563;--sidebar-width: 260px;--font-sans: "Inter", system-ui, -apple-system, sans-serif;--font-mono: "JetBrains Mono", monospace}*{box-sizing:border-box;margin:0;padding:0}body{background-color:var(--bg-color);color:var(--text-primary);font-family:var(--font-sans);overflow-x:hidden;-webkit-font-smoothing:antialiased}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:var(--bg-color)}::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.glass{background:#11111ab3;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border-color)}@keyframes fadeIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes pulseLive{0%{transform:scale(.95);opacity:.5}50%{transform:scale(1.15);opacity:1}to{transform:scale(.95);opacity:.5}}.animate-fade-in{animation:fadeIn .25s ease-out forwards}.live-indicator{display:inline-block;width:8px;height:8px;border-radius:50%;background-color:var(--success-color);box-shadow:0 0 8px var(--success-color);animation:pulseLive 2s infinite ease-in-out}.btn{display:inline-flex;align-items:center;gap:8px;padding:8px 16px;border-radius:6px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s ease;border:1px solid transparent;outline:none}.btn-primary{background:var(--accent-color);color:#fff;box-shadow:0 4px 12px var(--accent-glow)}.btn-primary:hover{filter:brightness(1.1);transform:translateY(-1px)}.btn-secondary{background:#ffffff0d;border-color:var(--border-color);color:var(--text-primary)}.btn-secondary:hover{background:#ffffff14}.btn-danger{background:#ef44441a;border-color:#ef444433;color:var(--error-color)}.btn-danger:hover{background:#ef444426}.input{background:#ffffff08;border:1px solid var(--border-color);color:var(--text-primary);padding:8px 12px;border-radius:6px;font-size:14px;font-family:var(--font-sans);outline:none;transition:border-color .2s}.input:focus{border-color:var(--accent-color)}.json-key{color:#93c5fd}.json-string{color:#86efac}.json-number{color:#fbbf24}.json-boolean{color:#c084fc}.json-null{color:#9ca3af}