npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@panudet_ingai/hookniew

v1.0.2

Published

HookNiew — Webhook reliability relay (Rust + Redis + Postgres). Queued -> Delivered -> Logged

Downloads

485

Readme

HookNiew — Webhook Reliability Service

เดิมชื่อ webhook-reliabilit เปลี่ยนเป็น HookNiew (Queued → Delivered → Logged)

บริการรับ Webhook ที่เน้นความน่าเชื่อถือ สร้างด้วย Rust (Axum) พร้อม Rate Limiting ผ่าน Redis, API Key Authentication, และการเชื่อมต่อ PostgreSQL (Supabase)

โปรเจกต์นี้มี 2 ส่วนหลักที่ทำงานร่วมกัน:

  1. HTTP Server — รับ request webhook ผ่าน Axum (port 6254)
  2. N-API Native Addon — expose ฟังก์ชัน Rust ให้ Node.js/TypeScript เรียกใช้ผ่าน napi-rs

Tech Stack

| ส่วน | เทคโนologi | |------|-----------| | Web Framework | Axum 0.8 | | Runtime | Tokio | | Database | SQLx + PostgreSQL (Supabase) | | Cache / Rate Limit | Redis (Upstash) + redis-rate | | Node.js Binding | NAPI-RS | | TLS | rustls |


Request Flow

เมื่อ client ยิง request มาที่ /v1 หรือ /v1/health:

Client Request
      │
      ▼
┌─────────────────────┐
│  Rate Limit         │  ← ตรวจ IP (X-Forwarded-For) ผ่าน Redis
│  (ratelimit.rs)     │     เกิน limit → 429 Too Many Requests
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│  API Key Auth       │  ← ตรวจ header `wh-rel-api-key`
│  (auth.rs)          │     ไม่มี/ผิด → 401 Unauthorized
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│  Handler            │  ← เช่น health check → 200 OK
│  (handlers/)        │
└─────────────────────┘

Rate limit ปัจจุบัน: 1 request / 5 วินาที, burst สูงสุด 10 (กำหนดใน ratelimit.rs)


โครงสร้าง Project

hookniew/
├── src/                        # Rust source code
│   ├── main.rs                 # Entry point ของ HTTP server
│   ├── lib.rs                  # Library root + N-API exports
│   │
│   ├── app/                    # Application bootstrap
│   │   ├── mod.rs              # build_state(), build_router(), run()
│   │   └── state.rs            # AppState (db pool + rate limiter)
│   │
│   ├── config/                 # การตั้งค่าเริ่มต้น
│   │   └── mod.rs              # โหลด .env + ติดตั้ง rustls crypto provider
│   │
│   ├── infra/                  # Infrastructure / External services
│   │   ├── postgres.rs         # เชื่อมต่อ Supabase PostgreSQL
│   │   └── redis.rs            # เชื่อมต่อ Redis + สร้าง rate limiter
│   │
│   ├── router/                 # HTTP routing
│   │   ├── mod.rs
│   │   └── v1/
│   │       ├── app_routers.rs  # กำหนด routes + middleware layers
│   │       └── middleware/
│   │           ├── auth.rs     # ตรวจ API key
│   │           └── ratelimit.rs# จำกัดจำนวน request
│   │
│   ├── handlers/               # Request handlers (business endpoints)
│   │   ├── health.rs           # GET /v1, /v1/health
│   │   └── api_key.rs          # validate key endpoint (เตรียมไว้)
│   │
│   ├── core/                   # Domain logic ที่ไม่ผูกกับ HTTP
│   │   ├── api_key.rs          # validate API key
│   │   └── version.rs          # ชื่อและเวอร์ชัน service
│   │
│   ├── sdk/                    # N-API SDK สำหรับ Node.js/TypeScript
│   │   ├── mod.rs              # export ฟังก์ชัน validate_api_key, get_service_info
│   │   ├── client.rs           # WebhookReliabilityClient (HTTP client)
│   │   └── types.rs            # Type definitions สำหรับ N-API
│   │
│   └── libraries/              # Utility helpers
│       └── env.rs              # อ่าน environment variables
│
├── tests/                      # Integration tests
│   ├── common/mod.rs           # init_test_env() สำหรับทุก test
│   ├── connect_db.rs           # ทดสอบ PostgreSQL connection
│   ├── redis.rs                # ทดสอบ Redis connection
│   └── rate_limit.rs           # ทดสอบ rate limiter + middleware
│
├── typescript/                 # TypeScript examples
├── __test__/                   # N-API addon tests (ava)
├── Cargo.toml                  # Rust dependencies
├── package.json                # Node.js / N-API build scripts
└── .env                        # Environment variables (ไม่ commit)

อธิบายแต่ละ Folder

src/app/ — Application Bootstrap

จุดเริ่มต้นของแอป HTTP

| ไฟล์ | หน้าที่ | |------|--------| | mod.rs | run() เริ่ม server, build_state() สร้าง DB pool + limiter, build_router() ประกอบ routes | | state.rs | AppState — เก็บ shared state ที่ middleware และ handlers ใช้ร่วมกัน |

main.rs เรียกแค่ hookniew::app::run() — logic ทั้งหมดอยู่ใน lib


src/config/ — Configuration

| ไฟล์ | หน้าที่ | |------|--------| | mod.rs | init() — โหลด .env และติดตั้ง rustls CryptoProvider (จำเป็นสำหรับ Redis TLS) |


src/infra/ — Infrastructure Layer

เชื่อมต่อ external services โดยไม่มี business logic

| ไฟล์ | หน้าที่ | |------|--------| | postgres.rs | สร้าง SQLx connection pool ไป Supabase (port 5432 session pooler แนะนำ) | | redis.rs | สร้าง Redis client และ redis_rate::Limiter สำหรับ rate limiting |

หมายเหตุ: ใช้ redis 2 เวอร์ชัน — redis 1.6 สำหรับงานทั่วไป, redis 0.29 (alias redis-v029) สำหรับ redis-rate crate


src/router/ — HTTP Routing

| ไฟล์ | หน้าที่ | |------|--------| | v1/app_routers.rs | กำหนด routes และเรียง middleware layers | | v1/middleware/auth.rs | ตรวจ header wh-rel-api-key ก่อนเข้า handler | | v1/middleware/ratelimit.rs | จำกัด request ตาม IP ผ่าน Redis token bucket |

Middleware order (จากนอก → ใน): Rate Limit → Auth → Handler


src/handlers/ — Request Handlers

รับ HTTP request หลังผ่าน middleware แล้ว ส่ง response กลับ

| ไฟล์ | Endpoint | หน้าที่ | |------|----------|--------| | health.rs | GET /v1, GET /v1/health | ตรวจสอบว่า service ยังทำงาน | | api_key.rs | (เตรียมไว้) | validate API key แบบ standalone |


src/core/ — Domain Logic

Logic ที่ไม่ผูกกับ HTTP framework — ใช้ได้ทั้ง server และ N-API

| ไฟล์ | หน้าที่ | |------|--------| | api_key.rs | ตรวจว่า API key ถูกต้องหรือไม่ | | version.rs | ชื่อและเวอร์ชัน service |


src/sdk/ — Node.js / TypeScript SDK

Expose Rust functions ให้ Node.js ผ่าน N-API

| ไฟล์ | หน้าที่ | |------|--------| | mod.rs | validate_api_key(), get_service_version(), get_service_info() | | client.rs | WebhookReliabilityClient — HTTP client เรียก API จาก TypeScript | | types.rs | Type definitions (HealthResponse, ValidateKeyResponse, etc.) |


tests/ — Integration Tests

ทดสอบกับ service จริง (ต้องมี .env ที่ตั้งค่าถูกต้อง)

| ไฟล์ | ทดสอบ | |------|--------| | connect_db.rs | เชื่อมต่อ Supabase + query ข้อมูล | | redis.rs | PING Redis ทั้ง client ปกติและ rate-limit client | | rate_limit.rs | Limiter โดยตรง + middleware คืน 429 + auth คืน 401 |


Environment Variables

สร้างไฟล์ .env ที่ root ของ project:

# Supabase PostgreSQL — ใช้ Session Pooler (port 5432) ไม่ใช่ Transaction (6543)
SUPABASE_URL_DATABASE=postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres

# Upstash Redis — ใช้ rediss:// สำหรับ TLS
REDIS_URL=rediss://default:[token]@[host].upstash.io:6379

| Variable | คำอธิบาย | |----------|----------| | SUPABASE_URL_DATABASE | PostgreSQL connection string จาก Supabase Dashboard | | REDIS_URL | Redis connection string จาก Upstash Dashboard |

ถ้า password มีอักขระพิเศษ (เช่น @) ต้อง URL-encode ก่อน (@ → %40)


Getting Started

Prerequisites

  • Rust (latest stable)
  • Node.js >= 22
  • Yarn 4.x
  • Supabase project + Upstash Redis instance

รัน HTTP Server

# ติดตั้ง dependencies
cargo build

# รัน server (port 6254)
cargo run

ทดสอบ Health Check

curl http://localhost:6254/v1/health \
  -H "wh-rel-api-key: PA-WEBHOOK-API-KEY"

Response:

{
  "status": "ok",
  "name": "Webhook Reliability Service",
  "version": "1.0.0"
}

รัน Tests

# Rust integration tests (ต้องมี .env)
cargo test

# N-API addon tests
yarn install
yarn build
yarn test

API Reference

Headers

| Header | Required | คำอธิบาย | |--------|----------|----------| | wh-rel-api-key | ✅ | API key สำหรับ authentication | | X-Forwarded-For | ❌ | IP ของ client (ใช้สำหรับ rate limiting) |

Endpoints

| Method | Path | Auth | คำอธิบาย | |--------|------|------|----------| | GET | / | ❌ | Hello World (ไม่มี middleware) | | GET | /v1 | ✅ | Health check | | GET | /v1/health | ✅ | Health check |

Response Codes

| Code | ความหมาย | |------|----------| | 200 | สำเร็จ | | 401 | ไม่มี API key หรือ key ไม่ถูกต้อง | | 429 | เกิน rate limit | | 500 | Redis error ระหว่าง rate limit check |


Build N-API Addon

yarn install
yarn build          # release build
yarn build:debug    # debug build

TypeScript client:

import { WebhookReliabilityClient } from 'hookniew'

const client = new WebhookReliabilityClient({
  apiKey: 'PA-WEBHOOK-API-KEY',
  baseUrl: 'http://localhost:6254',
})

const health = await client.health()
console.log(health)

License

MIT — ดู LICENSE