| dist | Loading last commit info... | |
| src | ||
| tests | ||
| .gitignore | ||
| CHANGELOG.md | ||
| README.md | ||
| package-lock.json | ||
| package.json | ||
| tsconfig.json | ||
| tsup.config.ts |
Islamic Network SDK (JavaScript/TypeScript)
Typed SDK for the Islamic Network APIs (AlAdhan + AlQuran) designed to work in React, Next.js, and React Native.
Supported APIs:
- AlAdhan (prayer times, Islamic calendar, qibla, Asma Al Husna)
- AlQuran (surahs, ayahs, sections, editions, search, sajda, meta)
- Boycott Israeli (companies, categories, search)
- Sermons (sources, languages, year/month sermon feeds)
Installation
npm install @islamicnetwork/sdk
# or
pnpm add @islamicnetwork/sdk
# or
yarn add @islamicnetwork/sdk
Usage
AlAdhan
import { AlAdhanClient, AlAdhanRequests } from "@islamic-network/sdk";
const client = AlAdhanClient.create();
const request = new AlAdhanRequests.DailyPrayerTimesByCoordinatesRequest(
"01-01-2025",
51.5194682,
-0.1360365,
new AlAdhanRequests.PrayerTimesOptions()
);
const response = await client.prayerTimes().dailyByCoordinates(request);
console.log(response.data.timings.Fajr);
import { AlAdhanClient, AlAdhanRequests } from "@islamic-network/sdk";
const client = AlAdhanClient.create();
const qibla = await client.qibla().direction(
new AlAdhanRequests.QiblaDirectionRequest(19.071017570421, 72.838622286762)
);
console.log(qibla.data.direction);
import { AlAdhanClient, AlAdhanRequests } from "@islamic-network/sdk";
const client = AlAdhanClient.create();
const asma = await client
.asmaAlHusna()
.byNumber(new AlAdhanRequests.AsmaAlHusnaByNumberRequest([1, 2, 3]));
console.log(asma.data[0]?.en.meaning);
Qibla Compass (Binary)
import { AlAdhanClient, AlAdhanRequests } from "@islamic-network/sdk";
const client = AlAdhanClient.create();
const image = await client
.qibla()
.compass(new AlAdhanRequests.QiblaCompassRequest(19.071017570421, 72.838622286762));
// Browser/React: build a Blob URL
const blob = new Blob([image.body], { type: image.contentType });
const url = URL.createObjectURL(blob);
AlQuran
Every method on AlQuranClient accepts either bare arguments or the
matching *Request class — pick whichever reads better:
import { AlQuranClient, AlQuranRequests } from "@islamicnetwork/sdk";
const client = AlQuranClient.create();
// Bare arguments — concise, recommended for app code.
const fatiha = await client.surahByEditions(1, ["quran-uthmani", "en.sahih"]);
const kursi = await client.ayahByNumberEdition("2:255", "en.sahih");
const page2 = await client.page(2);
const results = await client.search("mercy");
// Request-class form — still supported. Useful when you need to
// customise SectionOptions or pre-build a request elsewhere.
const ayah = await client.ayahByNumber(new AlQuranRequests.AyahByNumberRequest(5));
const editions = await client.editions(
new AlQuranRequests.EditionListRequest(null, "text", "en"),
);
Ayah references accept either a global number (1–6236) or a
sūrah-ayah string ("2:255"):
await client.ayahByNumberEdition(262, "en.sahih"); // by global number
await client.ayahByNumberEdition("2:255", "en.sahih"); // by surah:ayah
surahListWithMeta()
surahList joined with /meta so each sūrah carries firstPage (in the
604-page muṣḥaf) and firstAyahGlobalNumber (1–6236). /meta is
memoised on the client instance — repeated calls are one HTTP round-trip
in total.
const list = await client.surahListWithMeta();
for (const s of list.data) {
console.log(s.number, s.englishName, "page", s.firstPage);
}
searchEnriched()
Search and enrich each match with the Arabic counterpart (from
quran-uthmani) plus pre-computed character-offset highlights of the
query inside the match text. Heavy consumers can opt out via
SearchOptions.
const res = await client.searchEnriched("mercy");
for (const m of res.data.matches) {
console.log(`${m.surah.englishName} ${m.numberInSurah}: ${m.text}`);
console.log(" arabic:", m.arabic);
console.log(" matches at:", m.highlights); // e.g. [[4, 9], [42, 47]]
}
// Skip the Arabic counterpart fetches and/or highlight computation:
await client.searchEnriched("mercy", { includeArabic: false });
await client.searchEnriched("mercy", { computeHighlights: false });
await client.searchEnriched("mercy", { arabicFetchLimit: 10 }); // cap fetches
Also available: searchBySurahEnriched(query, surahNumber, options?)
and searchBySurahLanguageEnriched(query, surahNumber, language, options?).
Async factories
Every client offers createAsync(options?) alongside create(options?)
so async-scope callers don't have to mix sync + async factories:
const client = await AlQuranClient.createAsync();
Today createAsync resolves to the synchronous create result; the
async signature reserves the slot for future capability-probe work
(e.g. preloading /meta).
Error handling
Every method throws ApiException on non-2xx responses. Catch via
instanceof to access the statusCode and the upstream payload:
import { AlQuranClient, ApiException } from "@islamicnetwork/sdk";
const client = AlQuranClient.create();
try {
await client.surah(999); // out-of-range
} catch (e) {
if (e instanceof ApiException) {
if (e.statusCode === 404) // surah doesn't exist
if (e.statusCode === 429) // rate-limited
console.error(e.error?.status, e.error?.data);
} else {
throw e;
}
}
Boycott Israeli
import { BoycottIsraeliClient, BoycottIsraeliRequests } from "@islamic-network/sdk";
const client = BoycottIsraeliClient.create();
const categories = await client.categories(
new BoycottIsraeliRequests.CategoriesRequest(
new BoycottIsraeliRequests.PaginationOptions({ limit: 5 })
)
);
const companies = await client.search(
new BoycottIsraeliRequests.SearchRequest(
"food",
new BoycottIsraeliRequests.PaginationOptions({ limit: 2 })
)
);
console.log(categories.data[0]?.name);
console.log(companies.data[0]?.name);
Sermons
import { SermonsClient, SermonsRequests } from "@islamic-network/sdk";
const client = SermonsClient.create();
const sources = await client.sources(new SermonsRequests.SourcesRequest());
const languages = await client.languages(new SermonsRequests.LanguagesRequest());
const months = await client.yearSermons(
new SermonsRequests.YearSermonsRequest("uae-awqaf", 2021, SermonsRequests.SermonType.Friday)
);
const month = await client.monthSermons(
new SermonsRequests.MonthSermonsRequest("uae-awqaf", 2021, 7, SermonsRequests.SermonType.Friday)
);
console.log(sources[0]?.handle);
console.log(languages[0]?.code);
console.log(months[0]?.sermons[0]?.title);
console.log(month.month.number);
Configuration
Both clients accept the same options:
import { AlAdhanClient } from "@islamic-network/sdk";
const client = AlAdhanClient.create({
baseUrl: "https://api.aladhan.com/v1",
defaultHeaders: { "X-App": "my-app" },
defaultQuery: { iso8601: true },
timeoutMs: 10_000,
userAgent: "my-sdk-client",
fetch: globalThis.fetch // optional, provide for custom environments
});
Notes
- The SDK uses the global
fetchimplementation by default. Provide a customfetchfor non-standard environments. - Prayer timings preserve API field names (e.g.,
Fajr,Dhuhr,Firstthird). - Qibla compass requests return binary image data with a content type.
- Integration tests call live API endpoints and retry once on 429 or network errors.
Testing
npm test
Integration tests call the live APIs. When a 429 or timeout occurs, the client retries once after 1 second.