Skip to content

Repository files navigation

Bonyan-API

Node.jsTypeScriptFastifyDockerLicenseTestsOpenAPIdocswebsite


A unified Islamic API: Quran, Tafsir, Azkar, Hadith, Prayer Times, Hijri Date, and Qibla — with automatic multi-source fallback.

Please select your preferred language below / الرجاء اختيار لغتك المفضلة بالأسفل


English Version

Description

Bonyan-API is an enterprise-grade, high-performance API built with Node.js, Fastify, and TypeScript. It exposes a unified, type-safe data interface for every kind of Islamic digital content a modern web, mobile, or desktop application might need: full Quran text, audio recitations, Tafsir, Azkar (supplications), Hadith, prayer times, Hijri/Gregorian date conversion, and Qibla direction.

Every module is engineered around a single core idea: resilience through fallback. If a primary upstream source goes down, the API transparently retries against the next configured provider, returning a consistent shape to the client. Frequently-fetched data is memoized in-process to keep latency low and reduce load on third-party services.

Key Features

  • Multi-source fallback — every endpoint has 2+ upstream providers; if one fails (timeout, 5xx, malformed response, empty result), the next is tried automatically.
  • In-process caching — results are memoized with per-endpoint TTLs and concurrent calls are coalesced into a single upstream request.
  • Request timeouts — every upstream call is wrapped in AbortController so a slow source can't hang your server.
  • Rate limiting — built-in per-IP rate limit (configurable via RATE_LIMIT_MAX / RATE_LIMIT_WINDOW).
  • Production probes/health, /ready, and /metrics for uptime checks and monitoring.
  • Type-safe — written in strict TypeScript with noUncheckedIndexedAccess enabled.
  • Modular architecture — each domain (ayat, surah, reciters, azkar, tafsir, hadith, prayer, hijri, qibla) lives in its own route.ts / controller.ts / service.ts triplet.
  • Container-ready — multi-stage DOCKERFILE produces a minimal node:20-alpine runtime image.
  • CI/CD enforced — pull requests must pass ESLint, tsc, and Vitest before merge.

Modules & Endpoints

The root GET / returns a JSON catalogue of every registered route. GET /health returns liveness info, GET /ready returns readiness and cache stats, and GET /metrics exposes Prometheus text metrics.

Quran — Surah index — /surah

MethodPathDescription
GET/surahFull list of all 114 surahs
GET/surah/:idA single surah by id (1–114)
GET/surah/search?name=الفاتحةSearch surah by Arabic name

Fallback sources:mp3quran.netalquran.cloudquran.com

Quran — Ayat (verses) — /ayat

MethodPathDescription
GET/ayatThe full Quran text (cached for 24h)
GET/ayat/:idA single aya by absolute number (1–6236)
GET/ayat/:surah/aya/:idA single aya by surah + verse-in-surah
GET/ayat/search?text=الله&limit=50Search ayat by text (Arabic-normalized, ignores diacritics)

Fallback sources:alquran.cloud (Uthmani) → cdn.jsdelivr.net/gh/fawazahmed0/quran-api

Reciters & audio — /reciters

MethodPathDescription
GET/recitersAll reciters with their available moshafs
GET/reciters/:idA single reciter
GET/reciters/search?name=...Search reciter by Arabic name
GET/reciters/:id/surah/:surahResolve audio URL for a given reciter + surah

Fallback sources:mp3quran.netquran.com

Tafsir (exegesis) — /tafsir

MethodPathDescription
GET/tafsirList supported editions (muyassar, jalalayn, saadi, waseet, qurtubi)
GET/tafsir/:edition/:surahTafsir for a whole surah
GET/tafsir/:edition/:surah/:ayaTafsir for a single aya
GET/tafsir/:edition/:surah?aya=NSame, with the aya as a query param

Fallback sources:alquran.cloudquranenc.com

Azkar (supplications) — /azkar

MethodPathDescription
GET/azkarAll available categories (morning, evening, after prayer, …)
GET/azkar/:categoryItems inside a category
GET/azkar/randomA random zekr
GET/azkar/search?text=...&limit=50Search across all azkar

Fallback sources:nawafalqari/azkar-api (GitHub) → hisnmuslim.com

Hadith — /hadith

MethodPathDescription
GET/hadithList of available hadith books (Bukhari, Muslim, Abu-Dawud, …)
GET/hadith/:book?from=1&to=30Hadith range from a book (max 300 per request)
GET/hadith/:book/:numberA single hadith by its number
GET/hadith/random?book=bukhariA random hadith (optionally scoped to a book)

Fallback sources:api.hadith.gading.devcdn.jsdelivr.net/gh/sutanlab/hadith-api

Prayer Times — /prayer/times

MethodPathDescription
GET/prayer/times?latitude=21.4225&longitude=39.8262Today's timings for coordinates
GET/prayer/times?city=Mecca&country=SAToday's timings by city/country
GET/prayer/times?date=06-05-2026&latitude=...&longitude=...&method=4Custom date and calculation method

Fallback sources:api.aladhan.com/timingsapi.aladhan.com/timingsByCityapi.pray.zone (same-day coordinate requests only)

Hijri ↔ Gregorian — /hijri

MethodPathDescription
GET/hijri/todayToday's date in both calendars
GET/hijri/from-gregorian?date=06-05-2026Convert a gregorian date to hijri
GET/hijri/to-gregorian?date=18-11-1447Convert a hijri date to gregorian

Fallback sources:api.aladhan.com/gToHapi.aladhan.com/hToG

Qibla — /qibla

MethodPathDescription
GET/qibla?latitude=24.7136&longitude=46.6753Compass bearing (in degrees) toward the Kaaba

Fallback sources:api.aladhan.com/qibla → local great-circle computation (always succeeds)

Tech Stack

  • Runtime: Node.js (v20+ recommended)
  • Language: TypeScript (strict, NodeNext modules)
  • Framework: Fastify 5
  • Plugins:@fastify/cors, @fastify/rate-limit
  • Tooling: ESLint 10, Prettier, Vitest, tsx, dotenv
  • Package Manager: pnpm

Getting Started

Prerequisites

Local development

git clone https://github.com/BonyanOSS/Bonyan-API.git
cd Bonyan-API
pnpm install
cp .env.example .env # adjust PORT / RATE_LIMIT_* if needed
pnpm dev # starts Fastify with hot-reload via tsx watch

The server prints all registered routes on startup. Open http://localhost:3000/ for the live route catalogue.

Production build

pnpm lint:check # validates eslint + prettier
pnpm lint # applies eslint + prettier fixes
pnpm build # tsc → dist/
pnpm start # node dist/server.js

Environment variables

VariableDefaultPurpose
PORT3000HTTP listen port
HOST0.0.0.0Bind address
NODE_ENVproductionRuntime environment
RATE_LIMIT_MAX120Max requests per window per IP
RATE_LIMIT_WINDOW1 minuteRate-limit time window (parsed by @fastify/rate-limit)
CORS_ORIGIN*Allowed origins. Use comma-separated origins in production
TRUST_PROXYfalseTrust proxy headers for correct client IPs behind a proxy
LOG_LEVELinfoFastify logger level
CACHE_MAX_ENTRIES1000Maximum in-process cache entries

Docker

docker build -t bonyan-api .
docker run -p 3000:3000 --env-file .env bonyan-api

Testing

pnpm test# full vitest run (69 tests)
pnpm test:watch # interactive watch mode
pnpm test:coverage # generates coverage/lcov.info

Tests exercise:

  • The shared runWithFallback and memoize utilities (mocked).
  • Each module's controller — input validation, error shapes, status codes.
  • Live integration smoke tests that tolerate 200, 404, or 503 so the suite stays green even when an upstream is rate-limited or temporarily unreachable.

Project structure

src/
server.ts # Fastify bootstrap, plugins, route registration
modules/
ayat/ # full Quran text + search
surah/ # surah index
reciters/ # reciter directory + audio resolver
azkar/ # supplications (categories, random, search)
tafsir/ # multi-edition tafsir
hadith/ # 9-books hadith index + lookup
prayer/ # daily prayer timings
hijri/ # hijri ↔ gregorian conversion
qibla/ # qibla direction (with offline fallback)
utils/
fallback.ts # runWithFallback + fetchWithTimeout
cache.ts # in-memory memoize with TTL + concurrent-call coalescing
arabic.ts # Arabic-text normalization for search
http.ts # standard ok / fail / unavailable responders
types/
Api.ts # upstream payload shapes
Items.ts # canonical client-facing shapes
tests/ # vitest specs
.github/workflows/ # CI pipelines (lint, build, test, coverage)
DOCKERFILE # multi-stage production image

Contributing

We welcome contributions! Direct pushes to main are blocked — every change must go through a Pull Request, and CI must pass (ESLint + tsc + Vitest with coverage upload). See CONTRIBUTING.md, SECURITY.md, SUPPORT.md, SOURCES.md, and ROADMAP.md.

  1. Fork the repository and clone your fork.
  2. Create a feature branch: git checkout -b feature/your-feature.
  3. Lint your code: pnpm lint.
  4. Test your code: pnpm test.
  5. Commit using conventional messages: git commit -m 'feat(azkar): add evening category alias'.
  6. Push and open a PR against main.

When you add a new upstream source, please:

  • Wrap it with fetchWithTimeout so it can't hang the server.
  • Map its payload to the canonical type in src/types/Items.ts.
  • Add it as a fallback inside the existing service rather than creating a parallel pipeline.

License

This software is released under the MIT License.


النسخة العربية

وصف المشروع

Bonyan-API هي واجهة برمجة تطبيقات إسلامية متكاملة وعالية الأداء، مبنية على Node.js و Fastify و TypeScript. توفّر واجهة بيانات موحّدة وآمنة النوع لكل ما يحتاجه التطبيق الإسلامي الحديث من محتوى رقمي: نص القرآن الكريم كاملاً، التلاوات الصوتية، التفسير، الأذكار، الأحاديث، مواقيت الصلاة، التحويل بين التاريخ الهجري والميلادي، واتجاه القبلة.

كل وحدة في المشروع مبنية حول فكرة جوهرية واحدة: المرونة من خلال البدائل (Fallback). عند تعطّل المصدر الأساسي، يتنقّل النظام تلقائياً إلى المصدر التالي ضمن قائمة موثّقة من المزوّدين، ويُرجع للعميل نفس الشكل الموحّد دائماً. كما تُخزَّن النتائج المتكررة في الذاكرة لتقليل زمن الاستجابة وتخفيف الضغط على المصادر الخارجية.

المميزات الرئيسية

  • بدائل متعددة لكل نقطة نهاية — كل endpoint مدعوم بأكثر من مزوّد، وفي حال فشل أحدها (timeout / 5xx / استجابة فارغة) يُحاوَل التالي تلقائياً.
  • Cache داخلي — كل بيانات يتم جلبها تُحفظ في الذاكرة مع TTL مخصّص، والطلبات المتزامنة تُدمَج في طلب واحد.
  • مهلة لكل طلب خارجي — يُلفّ كل fetch بـ AbortController لمنع تعليق الخادم بسبب مصدر بطيء.
  • تحديد معدّل الطلبات (Rate Limit) — مدمج عبر @fastify/rate-limit (قابل للتعديل عبر متغيرات البيئة).
  • آمن النوع (Type-Safe) — مكتوب بالكامل في TypeScript مع strict و noUncheckedIndexedAccess.
  • بنية تركيبية — كل وحدة في مجلدها الخاص (route.ts / controller.ts / service.ts).
  • جاهز للحاوياتDOCKERFILE متعدد المراحل ينتج صورة node:20-alpine خفيفة.
  • CI/CD صارم — كل PR يجب أن يجتاز ESLint وبناء TypeScript واختبارات Vitest.

الوحدات ونقاط النهاية

GET / يُرجع قائمة بكل المسارات المسجّلة. GET /health يُرجع حالة الخادم.

السور — /surah

MethodPathالوصف
GET/surahكل السور الـ 114
GET/surah/:idسورة محددة (1–114)
GET/surah/search?name=الفاتحةبحث بالاسم العربي

البدائل:mp3quran.netalquran.cloudquran.com

الآيات — /ayat

MethodPathالوصف
GET/ayatكل القرآن (مُخزَّن لمدة 24 ساعة)
GET/ayat/:idآية برقمها المطلق (1–6236)
GET/ayat/:surah/aya/:idآية برقم السورة + ترتيبها داخلها
GET/ayat/search?text=الله&limit=50بحث في النص (يتجاهل التشكيل والاختلافات الإملائية)

البدائل:alquran.cloud (المصحف العثماني) → cdn.jsdelivr.net/gh/fawazahmed0/quran-api

القرّاء والصوتيات — /reciters

MethodPathالوصف
GET/recitersكل القرّاء مع المصاحف المتاحة
GET/reciters/:idقارئ محدد
GET/reciters/search?name=...بحث القارئ بالاسم
GET/reciters/:id/surah/:surahرابط الصوت لقارئ + سورة

البدائل:mp3quran.netquran.com

التفسير — /tafsir

MethodPathالوصف
GET/tafsirالإصدارات المدعومة (muyassar, jalalayn, saadi, waseet, qurtubi)
GET/tafsir/:edition/:surahتفسير سورة كاملة
GET/tafsir/:edition/:surah/:ayaتفسير آية واحدة

البدائل:alquran.cloudquranenc.com

الأذكار — /azkar

MethodPathالوصف
GET/azkarكل التصنيفات (الصباح، المساء، أذكار بعد الصلاة، …)
GET/azkar/:categoryعناصر تصنيف معين
GET/azkar/randomذكر عشوائي
GET/azkar/search?text=...بحث في كل الأذكار

البدائل:nawafalqari/azkar-api (GitHub) → hisnmuslim.com

الأحاديث — /hadith

MethodPathالوصف
GET/hadithالكتب المتاحة (البخاري، مسلم، أبو داود، …)
GET/hadith/:book?from=1&to=30جلب نطاق من الأحاديث
GET/hadith/:book/:numberحديث محدد برقمه
GET/hadith/random?book=bukhariحديث عشوائي

البدائل:api.hadith.gading.devcdn.jsdelivr.net/gh/sutanlab/hadith-api

مواقيت الصلاة — /prayer/times

MethodPathالوصف
GET/prayer/times?latitude=21.4225&longitude=39.8262مواقيت اليوم بالإحداثيات
GET/prayer/times?city=Mecca&country=SAمواقيت اليوم بالمدينة والدولة
GET/prayer/times?date=06-05-2026&...&method=4تاريخ مخصص + طريقة حساب

البدائل:api.aladhan.com/timingstimingsByCityapi.pray.zone

الهجري ↔ الميلادي — /hijri

MethodPathالوصف
GET/hijri/todayتاريخ اليوم بالتقويمين
GET/hijri/from-gregorian?date=06-05-2026ميلادي → هجري
GET/hijri/to-gregorian?date=18-11-1447هجري → ميلادي

البدائل:api.aladhan.com/gToHapi.aladhan.com/hToG

القبلة — /qibla

MethodPathالوصف
GET/qibla?latitude=24.7136&longitude=46.6753اتجاه القبلة بالدرجات

البدائل:api.aladhan.com/qibla → حساب محلي بصيغة الدائرة العظمى (لا يفشل أبداً)

التقنيات المستخدمة

  • بيئة التشغيل: Node.js (يُنصح بالإصدار 20 فما فوق)
  • اللغة: TypeScript
  • إطار العمل: Fastify 5
  • الإضافات:@fastify/cors، @fastify/rate-limit
  • الأدوات: ESLint 10، Prettier، Vitest، tsx، dotenv
  • مدير الحزم: pnpm

دليل التشغيل

المتطلبات

  • Node.js إصدار 20 أو أحدث
  • pnpm إصدار 10 أو أحدث
  • Docker (اختياري)

التشغيل المحلي

git clone https://github.com/BonyanOSS/Bonyan-API.git
cd Bonyan-API
pnpm install
cp .env.example .env
pnpm dev

الإنتاج

pnpm lint:check
pnpm lint
pnpm build
pnpm start

المتغيرات البيئية

المتغيرالقيمة الافتراضيةالوصف
PORT3000منفذ HTTP
HOST0.0.0.0عنوان الربط
NODE_ENVproductionبيئة التشغيل
RATE_LIMIT_MAX120الحد الأقصى للطلبات لكل IP
RATE_LIMIT_WINDOW1 minuteنافذة تحديد المعدّل
CORS_ORIGIN*النطاقات المسموح لها
TRUST_PROXYfalseالثقة بترويسات البروكسي
LOG_LEVELinfoمستوى سجلات Fastify
CACHE_MAX_ENTRIES1000حد عناصر الكاش الداخلي

Docker

docker build -t bonyan-api .
docker run -p 3000:3000 --env-file .env bonyan-api

الاختبارات

pnpm test# 69 اختبار
pnpm test:watch # وضع المراقبة
pnpm test:coverage # مع تقرير التغطية

الشراكة والمساهمة

نُرحّب بأي مساهمة! الدفع المباشر للفرع main ممنوع — يجب أن تمر كل مساهمة عبر Pull Request، وأن تجتاز خطوط CI.

  1. اعمل Fork للمستودع وانسخه محلياً.
  2. أنشئ فرعاً للميزة الجديدة: git checkout -b feature/your-feature.
  3. شغّل ESLint: pnpm lint.
  4. شغّل الاختبارات: pnpm test.
  5. أنشئ commit بصيغة Conventional: git commit -m 'feat(azkar): إضافة تصنيف جديد'.
  6. ادفع التغييرات وافتح PR على فرع main.

عند إضافة مصدر جديد:

  • استخدم fetchWithTimeout حتى لا يُعلِّق المصدر البطيء الخادم.
  • حوّل بيانات المصدر إلى الشكل الموحّد في src/types/Items.ts.
  • أضفه كـ fallback ضمن الـ service الموجود بدلاً من إنشاء مسار مستقل.

الترخيص

هذا المشروع مُرخَّص بموجب رخصة MIT.

About

API for broadcasting the Quran and supplications with automatic fallback between multiple sources and a unified data interface

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages