Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions apps/docs/content/docs/tafsir.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: Tafsir API
description: Retrieve tafsir text by surah, page, juz, hizb, rub, manzil, ruku, or ayah.
---

The Tafsir API gives you direct access to tafsir content in the same style as the rest of the SDK.

## Get a Single Tafsir

```ts
const tafsir = await client.tafsir.get("169", {
chapterNumber: 1,
});

console.log(tafsir.tafsirs[0]);
```

### TafsirResponse Type

<auto-type-table
path="../../../../packages/api/src/types/api/TafsirResponse.ts"
name="TafsirResponse"
/>

## Get Tafsirs by Chapter

```ts
const surahTafsirs = await client.tafsir.findByChapter("169", "1", {
page: 1,
perPage: 10,
});
```

## Get Tafsirs by Page

```ts
const pageTafsirs = await client.tafsir.findByPage("169", "1");
```

## Get Tafsirs by Juz

```ts
const juzTafsirs = await client.tafsir.findByJuz("169", "1");
```

## Get Tafsirs by Hizb

```ts
const hizbTafsirs = await client.tafsir.findByHizb("169", "1");
```

## Get Tafsirs by Rub El Hizb

```ts
const rubTafsirs = await client.tafsir.findByRubElHizb("169", "1");
const rubAlias = await client.tafsir.findByRub("169", "1");
```

## Get Tafsirs by Manzil

```ts
const manzilTafsirs = await client.tafsir.findByManzil("169", "1");
```

## Get Tafsirs by Ruku

```ts
const rukuTafsirs = await client.tafsir.findByRuku("169", "1");
```

## Get Tafsirs by Ayah

```ts
const ayahTafsirs = await client.tafsir.findByAyah("169", "1:1");
```

## Tafsir and Resources

```ts
const availableTafsirs = await client.resources.findAllTafsirs();
const tafsirInfo = await client.resources.findTafsirInfo("169");
```
27 changes: 27 additions & 0 deletions packages/api/src/runtime/create-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { QuranHadithReferences } from "@/sdk/hadith-references";
import { QuranJuzs } from "@/sdk/juzs";
import { QuranResources } from "@/sdk/resources";
import { QuranSearch } from "@/sdk/search";
import { QuranTafsir } from "@/sdk/tafsir";
import { QuranVerses } from "@/sdk/verses";

type RuntimeClientConfig = PublicClientConfig | ServerClientConfig;
Expand Down Expand Up @@ -360,6 +361,7 @@ const createContentFacade = (
audio: QuranAudio,
hadithReferences: QuranHadithReferences,
resources: QuranResources,
tafsir: QuranTafsir,
raw: Record<string, RawOperation>,
) => {
return {
Expand Down Expand Up @@ -409,6 +411,28 @@ const createContentFacade = (
list: () => juzs.findAll(),
},
raw,
tafsir: {
get: (tafsirId: string | number, query?: ApiParams) =>
tafsir.get(tafsirId, query),
byAyah: (resourceId: string | number, verseKey: VerseKey, query?: ApiParams) =>
tafsir.findByAyah(resourceId, verseKey, query),
byChapter: (resourceId: string | number, chapterId: ChapterId, query?: ApiParams) =>
tafsir.findByChapter(resourceId, chapterId, query),
byHizb: (resourceId: string | number, hizb: HizbNumber, query?: ApiParams) =>
tafsir.findByHizb(resourceId, hizb, query),
byJuz: (resourceId: string | number, juz: JuzNumber, query?: ApiParams) =>
tafsir.findByJuz(resourceId, juz, query),
byManzil: (resourceId: string | number, manzilNumber: number | string, query?: ApiParams) =>
tafsir.findByManzil(resourceId, manzilNumber, query),
byPage: (resourceId: string | number, page: PageNumber, query?: ApiParams) =>
tafsir.findByPage(resourceId, page, query),
byRub: (resourceId: string | number, rubNumber: RubNumber, query?: ApiParams) =>
tafsir.findByRub(resourceId, rubNumber, query),
byRubElHizb: (resourceId: string | number, rubElHizbNumber: RubNumber, query?: ApiParams) =>
tafsir.findByRubElHizb(resourceId, rubElHizbNumber, query),
byRuku: (resourceId: string | number, rukuNumber: number | string, query?: ApiParams) =>
tafsir.findByRuku(resourceId, rukuNumber, query),
},
resources: {
findSnapshot: (
resourceGroup: ContentSyncResourceGroup,
Expand Down Expand Up @@ -478,6 +502,7 @@ export const createRuntimeClient = (
const hadithReferences = new QuranHadithReferences(fetcher);
const resources = new QuranResources(fetcher);
const searchClient = new QuranSearch(fetcher);
const tafsir = new QuranTafsir(fetcher);

const raw = {
auth: {
Expand Down Expand Up @@ -505,6 +530,7 @@ export const createRuntimeClient = (
audio,
hadithReferences,
resources,
tafsir,
raw.content.v4,
);
const authV1 = createAuthFacade(fetcher);
Expand Down Expand Up @@ -554,6 +580,7 @@ export const createRuntimeClient = (
raw,
resources,
search,
tafsir,
verses,
};
};
1 change: 1 addition & 0 deletions packages/api/src/runtime/create-public-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ export const createPublicRuntimeClient = (config: PublicClientConfig) => {
},
chapters: serverOnlyGuard,
clearCachedTokens: () => fetcher.clearCachedTokens(),
tafsir: serverOnlyGuard,
content: serverOnlyGuard,
getUserSession: () => fetcher.getUserSession(),
hadithReferences: serverOnlyGuard,
Expand Down
3 changes: 3 additions & 0 deletions packages/api/src/sdk/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { QuranHadithReferences } from "./hadith-references";
import { QuranJuzs } from "./juzs";
import { QuranResources } from "./resources";
import { QuranSearch } from "./search";
import { QuranTafsir } from "./tafsir";
import { QuranVerses } from "./verses";

const { camelizeKeys } = humps;
Expand Down Expand Up @@ -138,6 +139,7 @@ export class QuranClient {
public readonly hadithReferences: QuranHadithReferences;
public readonly resources: QuranResources;
public readonly search: QuranSearch;
public readonly tafsir: QuranTafsir;

constructor(config: QuranClientConfig) {
this.config = {
Expand All @@ -161,6 +163,7 @@ export class QuranClient {
this.hadithReferences = new QuranHadithReferences(this.fetcher);
this.resources = new QuranResources(this.fetcher);
this.search = new QuranSearch(this.fetcher);
this.tafsir = new QuranTafsir(this.fetcher);
}

public getConfig(): QuranClientConfig {
Expand Down
197 changes: 197 additions & 0 deletions packages/api/src/sdk/tafsir.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import type {
BaseApiParams,
ChapterId,
HizbNumber,
JuzNumber,
PageNumber,
QuranFetchClient,
RubNumber,
TafsirResponse,
VerseKey,
} from "@/types";
import {
isValidChapterId,
isValidHizb,
isValidJuz,
isValidQuranPage,
isValidRub,
isValidVerseKey,
} from "@/utils";

type GetTafsirOptions = BaseApiParams & {
chapterNumber?: ChapterId;
fields?: string;
page?: number;
perPage?: number;
};

/**
* Tafsir API methods
*/
export class QuranTafsir {
constructor(private fetcher: QuranFetchClient) {}

/**
* Get a single tafsir.
* @description https://api-docs.quran.foundation/docs/content_apis_versioned/tafsir/
* @param {string | number} tafsirId tafsir id
* @param {GetTafsirOptions} options
* @example
* client.tafsir.get('169', { chapterNumber: 1 })
*/
async get(
tafsirId: string | number,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/quran/tafsirs/${tafsirId}`,
options,
);
}

/**
* Get tafsirs for a specific chapter.
* @description https://api-docs.quran.foundation/docs/content_apis_versioned/4.0.0/list-surah-tafsirs/
* @param {string | number} resourceId tafsir resource id
* @param {ChapterId} chapterNumber chapter id, minimum 1, maximum 114
* @param {GetTafsirOptions} options
* @example
* client.tafsir.findByChapter('169', '1')
*/
async findByChapter(
resourceId: string | number,
chapterNumber: ChapterId,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
if (!isValidChapterId(chapterNumber)) throw new Error("Invalid chapter id");

return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_chapter/${chapterNumber}`,
options,
);
}

/**
* Get tafsirs for a specific page.
*/
async findByPage(
resourceId: string | number,
pageNumber: PageNumber,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
if (!isValidQuranPage(pageNumber)) throw new Error("Invalid page number");

return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_page/${pageNumber}`,
options,
);
}

/**
* Get tafsirs for a specific juz.
*/
async findByJuz(
resourceId: string | number,
juzNumber: JuzNumber,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
if (!isValidJuz(juzNumber)) throw new Error("Invalid juz");

return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_juz/${juzNumber}`,
options,
);
}

/**
* Get tafsirs for a specific rub el hizb.
*/
async findByRubElHizb(
resourceId: string | number,
rubElHizbNumber: RubNumber,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
if (!isValidRub(rubElHizbNumber)) throw new Error("Invalid rub number");

return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_rub_el_hizb/${rubElHizbNumber}`,
options,
);
}

/**
* Alias for rub el hizb.
*/
async findByRub(
resourceId: string | number,
rubNumber: RubNumber,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
if (!isValidRub(rubNumber)) throw new Error("Invalid rub number");

return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_rub/${rubNumber}`,
options,
);
}
Comment on lines +106 to +136

/**
* Get tafsirs for a specific hizb.
*/
async findByHizb(
resourceId: string | number,
hizbNumber: HizbNumber,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
if (!isValidHizb(hizbNumber)) throw new Error("Invalid hizb");

return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_hizb/${hizbNumber}`,
options,
);
}

/**
* Get tafsirs for a specific manzil.
*/
async findByManzil(
resourceId: string | number,
manzilNumber: number | string,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_manzil/${manzilNumber}`,
options,
);
}

/**
* Get tafsirs for a specific ruku.
*/
async findByRuku(
resourceId: string | number,
rukuNumber: number | string,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_ruku/${rukuNumber}`,
options,
);
}

/**
* Get tafsirs for a specific ayah.
*/
async findByAyah(
resourceId: string | number,
verseKey: VerseKey,
options?: GetTafsirOptions,
): Promise<TafsirResponse> {
if (!isValidVerseKey(verseKey)) throw new Error("Invalid verse key");

return this.fetcher.fetch<TafsirResponse>(
`/content/api/v4/tafsirs/${resourceId}/by_ayah/${verseKey}`,
options,
);
}
}
15 changes: 15 additions & 0 deletions packages/api/src/types/api/TafsirResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Pagination } from "./Pagination";
import type { Tafsir } from "./Tafsir";

export interface TafsirMeta {
tafsirName?: string;
authorName?: string;
}

export interface TafsirResponse {
tafsirs: Tafsir[];
meta?: TafsirMeta;
pagination?: Omit<Pagination, "nextPage"> & {
nextPage: number | null;
};
}
Loading