From aa927aadb9570dd5b3238fa5cbca4a3658094523 Mon Sep 17 00:00:00 2001 From: Ahmad Bilal Date: Thu, 29 Aug 2024 11:30:01 +0500 Subject: [PATCH] imp(types): add types and mappers for hadith apis --- src/azkar/azkar.ts | 10 +-- src/hadith/hadith-book-lang-mapper.ts | 70 ++++++++++++++++ src/hadith/hadith-response-mappers.ts | 114 ++++++++++++++++++++++++++ src/hadith/hadith.ts | 102 +++++------------------ src/types/hadith-api-response.ts | 82 ++++++++++++++++++ src/types/hadith-by-section.ts | 18 ++++ src/types/hadith-edition.ts | 24 ++++++ src/types/hadith-info.ts | 27 ++++++ src/types/hadith-object.ts | 18 ++++ src/types/index.ts | 4 + 10 files changed, 384 insertions(+), 85 deletions(-) create mode 100644 src/hadith/hadith-book-lang-mapper.ts create mode 100644 src/hadith/hadith-response-mappers.ts create mode 100644 src/types/hadith-api-response.ts create mode 100644 src/types/hadith-by-section.ts create mode 100644 src/types/hadith-edition.ts create mode 100644 src/types/hadith-info.ts create mode 100644 src/types/hadith-object.ts diff --git a/src/azkar/azkar.ts b/src/azkar/azkar.ts index 61dda5f..006d784 100644 --- a/src/azkar/azkar.ts +++ b/src/azkar/azkar.ts @@ -3,10 +3,10 @@ import { AzkarCategoriesEnum } from '../types/azkar-categories.enum'; import { Zikr } from '../types/zikr'; export class Azkar { - private azkars: AzkarCollectionType; + private azkarCollection: AzkarCollectionType; constructor() { - this.azkars = AzkarCollection; + this.azkarCollection = AzkarCollection; } /** @@ -15,7 +15,7 @@ export class Azkar { * @returns Zikr[] - List of azkars in the category or undefined */ public getByCategory(category: AzkarCategoriesEnum): Zikr[] { - return this.azkars[category]; + return this.azkarCollection[category]; } /** @@ -34,7 +34,7 @@ export class Azkar { * @returns {Map} - Map of all azkars by category */ public getAll(): Map { - return new Map(Object.entries(this.azkars)); + return new Map(Object.entries(this.azkarCollection)); } /** @@ -42,7 +42,7 @@ export class Azkar { * @returns {Zikr} - Random azkar */ public getRandom(): Zikr { - const allAzkars = Object.values(this.azkars).flat(); + const allAzkars = Object.values(this.azkarCollection).flat(); return this.randomValueFromArray(allAzkars); } diff --git a/src/hadith/hadith-book-lang-mapper.ts b/src/hadith/hadith-book-lang-mapper.ts new file mode 100644 index 0000000..e42a262 --- /dev/null +++ b/src/hadith/hadith-book-lang-mapper.ts @@ -0,0 +1,70 @@ +import { HadithLangEnum } from '../types/hadith-lang.enum'; +import { HadithBook } from '../types/hadith.enum'; + +export const hadithBookLanguages: Record = { + [HadithBook.AbuDawud]: [ + HadithLangEnum.Arabic, + HadithLangEnum.Bengali, + HadithLangEnum.English, + HadithLangEnum.Indonesian, + HadithLangEnum.Russian, + HadithLangEnum.Turkish, + HadithLangEnum.Urdu, + ], + [HadithBook.Bukhari]: [ + HadithLangEnum.Arabic, + HadithLangEnum.Bengali, + HadithLangEnum.English, + HadithLangEnum.Indonesian, + HadithLangEnum.Russian, + HadithLangEnum.Tamil, + HadithLangEnum.Turkish, + HadithLangEnum.Urdu, + ], + [HadithBook.Dehlawi]: [HadithLangEnum.Arabic, HadithLangEnum.English], + [HadithBook.IbnMajah]: [ + HadithLangEnum.Arabic, + HadithLangEnum.Bengali, + HadithLangEnum.English, + HadithLangEnum.Indonesian, + HadithLangEnum.Turkish, + HadithLangEnum.Urdu, + ], + [HadithBook.MuwattaMalik]: [ + HadithLangEnum.Arabic, + HadithLangEnum.English, + HadithLangEnum.Turkish, + HadithLangEnum.Urdu, + ], + [HadithBook.Muslim]: [ + HadithLangEnum.Arabic, + HadithLangEnum.Bengali, + HadithLangEnum.English, + HadithLangEnum.Indonesian, + HadithLangEnum.Russian, + HadithLangEnum.Tamil, + HadithLangEnum.Turkish, + HadithLangEnum.Urdu, + ], + [HadithBook.Nasai]: [ + HadithLangEnum.Arabic, + HadithLangEnum.Bengali, + HadithLangEnum.English, + HadithLangEnum.Indonesian, + HadithLangEnum.Russian, + HadithLangEnum.Tamil, + HadithLangEnum.Turkish, + HadithLangEnum.Urdu, + ], + [HadithBook.Tirmidhi]: [ + HadithLangEnum.Arabic, + HadithLangEnum.Bengali, + HadithLangEnum.English, + HadithLangEnum.Indonesian, + HadithLangEnum.Russian, + HadithLangEnum.Turkish, + HadithLangEnum.Urdu, + ], + [HadithBook.Nawawi40]: [HadithLangEnum.Arabic, HadithLangEnum.Bengali, HadithLangEnum.English], + [HadithBook.Qudsi]: [HadithLangEnum.Arabic, HadithLangEnum.English], +}; diff --git a/src/hadith/hadith-response-mappers.ts b/src/hadith/hadith-response-mappers.ts new file mode 100644 index 0000000..c400900 --- /dev/null +++ b/src/hadith/hadith-response-mappers.ts @@ -0,0 +1,114 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { HadithInfo } from '../types'; +import { HadithApiResponse, HadithEditionApiResponse, HadithInfoApiResponse } from '../types/hadith-api-response'; +import { HadithBySection } from '../types/hadith-by-section'; +import { HadithEdition } from '../types/hadith-edition'; +import { HadithObject } from '../types/hadith-object'; + +export function mapHadithInfoResponse(response: HadithInfoApiResponse): HadithInfo { + const hadithInfo: HadithInfo = {}; + + Object.keys(response).forEach((key) => { + const apiHadith = response[key]; + + hadithInfo[key] = { + hadiths: apiHadith.hadiths.map((hadith) => ({ + arabicNumber: hadith.arabicnumber, + grades: hadith.grades, + hadithNumber: hadith.hadithnumber, + reference: hadith.reference, + })) as any, + metadata: { + lastHadithNumber: apiHadith.metadata.last_hadithnumber, + name: apiHadith.metadata.name, + sections: Object.keys(apiHadith.metadata.section_details).map((sectionKey) => { + const sectionData = apiHadith.metadata.section_details[parseInt(sectionKey)]; + + return { + name: apiHadith.metadata.sections[parseInt(sectionKey)], + details: { + arabicNumberFirst: sectionData.arabicnumber_first, + arabicNumberLast: sectionData.arabicnumber_last, + hadithNumberFirst: sectionData.hadithnumber_first, + hadithNumberLast: sectionData.hadithnumber_last, + }, + }; + }) as any, + }, + }; + }); + + return hadithInfo; +} + +export function mapHadithEditionResponse(apiHadith: HadithEditionApiResponse): HadithEdition { + const edition: HadithEdition = { + hadiths: apiHadith.hadiths.map((hadith) => ({ + grades: hadith.grades, + hadithNumber: hadith.hadithnumber, + reference: hadith.reference, + text: hadith.text, + })) as any, + metadata: { + name: apiHadith.metadata.name, + sections: Object.keys(apiHadith.metadata.section_details).map((sectionKey) => { + const sectionData = apiHadith.metadata.section_details[parseInt(sectionKey)]; + + return { + name: apiHadith.metadata.sections[parseInt(sectionKey)], + details: { + arabicNumberFirst: sectionData.arabicnumber_first, + arabicNumberLast: sectionData.arabicnumber_last, + hadithNumberFirst: sectionData.hadithnumber_first, + hadithNumberLast: sectionData.hadithnumber_last, + }, + }; + }) as any, + }, + }; + + return edition; +} + +export function mapHadithSectionResponse(resp: HadithApiResponse, sectionNo: number): HadithBySection { + return { + metadata: { + name: resp.metadata.name, + section: resp.metadata.section[sectionNo], + sectionDetails: { + arabicNumberFirst: resp.metadata.section_detail[sectionNo].arabicnumber_first, + arabicNumberLast: resp.metadata.section_detail[sectionNo].arabicnumber_last, + hadithNumberFirst: resp.metadata.section_detail[sectionNo].hadithnumber_first, + hadithNumberLast: resp.metadata.section_detail[sectionNo].hadithnumber_last, + }, + }, + hadiths: resp.hadiths.map((hadith) => ({ + arabicNumber: hadith.arabicnumber, + grades: hadith.grades, + hadithNumber: hadith.hadithnumber, + reference: hadith.reference, + text: hadith.text, + })), + }; +} + +export function mapHadithResponse(resp: HadithApiResponse): HadithObject { + return { + metadata: { + name: resp.metadata.name, + section: resp.metadata.section[1], + sectionDetails: { + arabicNumberFirst: resp.metadata.section_detail[1].arabicnumber_first, + arabicNumberLast: resp.metadata.section_detail[1].arabicnumber_last, + hadithNumberFirst: resp.metadata.section_detail[1].hadithnumber_first, + hadithNumberLast: resp.metadata.section_detail[1].hadithnumber_last, + }, + }, + hadith: { + hadithNumber: resp.hadiths[0].hadithnumber, + arabicNumber: resp.hadiths[0].arabicnumber, + text: resp.hadiths[0].text, + grades: resp.hadiths[0].grades, + }, + }; +} diff --git a/src/hadith/hadith.ts b/src/hadith/hadith.ts index c5dced2..b72cc21 100644 --- a/src/hadith/hadith.ts +++ b/src/hadith/hadith.ts @@ -1,74 +1,12 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ import { HadithBook } from '../types/hadith.enum'; import { HadithLangEnum } from '../types/hadith-lang.enum'; - -const hadithBookLanguages: Record = { - [HadithBook.AbuDawud]: [ - HadithLangEnum.Arabic, - HadithLangEnum.Bengali, - HadithLangEnum.English, - HadithLangEnum.Indonesian, - HadithLangEnum.Russian, - HadithLangEnum.Turkish, - HadithLangEnum.Urdu, - ], - [HadithBook.Bukhari]: [ - HadithLangEnum.Arabic, - HadithLangEnum.Bengali, - HadithLangEnum.English, - HadithLangEnum.Indonesian, - HadithLangEnum.Russian, - HadithLangEnum.Tamil, - HadithLangEnum.Turkish, - HadithLangEnum.Urdu, - ], - [HadithBook.Dehlawi]: [HadithLangEnum.Arabic, HadithLangEnum.English], - [HadithBook.IbnMajah]: [ - HadithLangEnum.Arabic, - HadithLangEnum.Bengali, - HadithLangEnum.English, - HadithLangEnum.Indonesian, - HadithLangEnum.Turkish, - HadithLangEnum.Urdu, - ], - [HadithBook.MuwattaMalik]: [ - HadithLangEnum.Arabic, - HadithLangEnum.English, - HadithLangEnum.Turkish, - HadithLangEnum.Urdu, - ], - [HadithBook.Muslim]: [ - HadithLangEnum.Arabic, - HadithLangEnum.Bengali, - HadithLangEnum.English, - HadithLangEnum.Indonesian, - HadithLangEnum.Russian, - HadithLangEnum.Tamil, - HadithLangEnum.Turkish, - HadithLangEnum.Urdu, - ], - [HadithBook.Nasai]: [ - HadithLangEnum.Arabic, - HadithLangEnum.Bengali, - HadithLangEnum.English, - HadithLangEnum.Indonesian, - HadithLangEnum.Russian, - HadithLangEnum.Tamil, - HadithLangEnum.Turkish, - HadithLangEnum.Urdu, - ], - [HadithBook.Tirmidhi]: [ - HadithLangEnum.Arabic, - HadithLangEnum.Bengali, - HadithLangEnum.English, - HadithLangEnum.Indonesian, - HadithLangEnum.Russian, - HadithLangEnum.Turkish, - HadithLangEnum.Urdu, - ], - [HadithBook.Nawawi40]: [HadithLangEnum.Arabic, HadithLangEnum.Bengali, HadithLangEnum.English], - [HadithBook.Qudsi]: [HadithLangEnum.Arabic, HadithLangEnum.English], -}; +import { hadithBookLanguages } from './hadith-book-lang-mapper'; +import { HadithObject } from '../types/hadith-object'; +import { HadithApiResponse, HadithEditionApiResponse, HadithInfoApiResponse } from '../types/hadith-api-response'; +import * as HadithMappers from './hadith-response-mappers'; +import { HadithInfo } from '../types'; +import { HadithBySection } from '../types/hadith-by-section'; +import { HadithEdition } from '../types/hadith-edition'; export class Hadith { private baseUrl: string; @@ -98,7 +36,7 @@ export class Hadith { * @param prettified - Whether to fetch the prettified JSON (default is true). * @returns A promise that resolves with the fetched data. */ - public async getAllEditions(prettified: boolean = true): Promise { + private async getAllEditions(prettified: boolean = true) { const url = `${this.baseUrl}/editions${prettified ? '.json' : '.min.json'}`; return this.fetchData(url); } @@ -109,10 +47,11 @@ export class Hadith { * @param lang - The language of the Hadith edition (optional). * @returns A promise that resolves with the fetched data. */ - public async getEdition(book: HadithBook, lang?: HadithLangEnum): Promise { + public async getEdition(book: HadithBook, lang?: HadithLangEnum): Promise { const slug = this.getEditionSlug(book, lang); const url = `${this.baseUrl}/editions/${slug}.json`; - return this.fetchData(url); + const resp = (await this.fetchData(url)) as HadithEditionApiResponse; + return HadithMappers.mapHadithEditionResponse(resp); } /** @@ -122,10 +61,11 @@ export class Hadith { * @param lang - The language of the Hadith edition (optional). * @returns A promise that resolves with the fetched data. */ - public async getHadith(book: HadithBook, hadithNo: number, lang?: HadithLangEnum): Promise { + public async getHadith(book: HadithBook, hadithNo: number, lang?: HadithLangEnum): Promise { const slug = this.getEditionSlug(book, lang); const url = `${this.baseUrl}/editions/${slug}/${hadithNo}.json`; - return this.fetchData(url); + const resp = (await this.fetchData(url)) as HadithApiResponse; + return HadithMappers.mapHadithResponse(resp); } /** @@ -135,19 +75,21 @@ export class Hadith { * @param lang - The language of the Hadith edition (optional). * @returns A promise that resolves with the fetched data. */ - public async getSection(book: HadithBook, sectionNo: number, lang?: HadithLangEnum): Promise { + public async getSection(book: HadithBook, sectionNo: number, lang?: HadithLangEnum): Promise { const slug = this.getEditionSlug(book, lang); const url = `${this.baseUrl}/editions/${slug}/sections/${sectionNo}.json`; - return this.fetchData(url); + const resp = (await this.fetchData(url)) as HadithApiResponse; + return HadithMappers.mapHadithSectionResponse(resp, sectionNo); } /** * Fetches general information about the available Hadith books. - * @returns A promise that resolves with the fetched data. + * @returns A promise that resolves with the type HadithInfo. */ - public async getInfo(): Promise { + public async getBooksInfo(): Promise { const url = `${this.baseUrl}/info.json`; - return this.fetchData(url); + const resp = (await this.fetchData(url)) as HadithInfoApiResponse; + return HadithMappers.mapHadithInfoResponse(resp); } /** @@ -155,7 +97,7 @@ export class Hadith { * @param url - The URL to fetch data from. * @returns A promise that resolves with the fetched data or throws an error if the fetch fails. */ - private async fetchData(url: string): Promise { + private async fetchData(url: string) { try { const response = await fetch(url); if (!response.ok) { diff --git a/src/types/hadith-api-response.ts b/src/types/hadith-api-response.ts new file mode 100644 index 0000000..fa35a51 --- /dev/null +++ b/src/types/hadith-api-response.ts @@ -0,0 +1,82 @@ +export interface HadithApiResponse { + metadata: HadithMetadata; + hadiths: HadithContent[]; +} + +interface HadithMetadata { + name: string; + section: Record; + section_detail: Record< + string, + { + arabicnumber_first: string | number; + arabicnumber_last: string | number; + hadithnumber_first: string | number; + hadithnumber_last: string | number; + } + >; +} + +interface HadithContent { + hadithnumber: number; + arabicnumber: number; + text: string; + grades: [{ name: string; grade: string }]; + reference: [{ book: number; hadith: number }]; +} + +export interface HadithInfoApiResponse { + [key: string]: { + hadiths: [ + { + arabicnumber: string | number; + grades: [{ name: string; grade: string }]; + hadithnumber: string | number; + reference: { book: number; hadith: number }; + }, + ]; + metadata: { + last_hadithnumber: string | number; + name: string; + section_details: [ + Record< + string, + { + arabicnumber_first: string | number; + arabicnumber_last: string | number; + hadithnumber_first: string | number; + hadithnumber_last: string | number; + } + >, + ]; + sections: [Record]; + }; + }; +} + +export interface HadithEditionApiResponse { + hadiths: [ + { + grades: [{ name: string; grade: string }]; + hadithnumber: string | number; + reference: { book: number; hadith: number }; + text: string; + }, + ]; + metadata: { + last_hadithnumber: string | number; + name: string; + section_details: [ + Record< + string, + { + arabicnumber_first: string | number; + arabicnumber_last: string | number; + hadithnumber_first: string | number; + hadithnumber_last: string | number; + } + >, + ]; + sections: [Record]; + }; +} diff --git a/src/types/hadith-by-section.ts b/src/types/hadith-by-section.ts new file mode 100644 index 0000000..e636173 --- /dev/null +++ b/src/types/hadith-by-section.ts @@ -0,0 +1,18 @@ +export interface HadithBySection { + metadata: { + name: string; + section: string; + sectionDetails: { + arabicNumberFirst: string | number; + arabicNumberLast: string | number; + hadithNumberFirst: string | number; + hadithNumberLast: string | number; + }; + }; + hadiths: { + hadithNumber: string | number; + arabicNumber: string | number; + text: string; + grades: [{ name: string; grade: string }]; + }[]; +} diff --git a/src/types/hadith-edition.ts b/src/types/hadith-edition.ts new file mode 100644 index 0000000..d368672 --- /dev/null +++ b/src/types/hadith-edition.ts @@ -0,0 +1,24 @@ +export interface HadithEdition { + hadiths: [ + { + grades: [{ name: string; grade: string }]; + hadithNumber: string | number; + reference: { book: number; hadith: number }; + text: string; + }, + ]; + metadata: { + name: string; + sections: [ + { + name: string; + details: { + arabicNumberFirst: string | number; + arabicNumberLast: string | number; + hadithNumberFirst: string | number; + hadithNumberLast: string | number; + }; + }, + ]; + }; +} diff --git a/src/types/hadith-info.ts b/src/types/hadith-info.ts new file mode 100644 index 0000000..f76eb00 --- /dev/null +++ b/src/types/hadith-info.ts @@ -0,0 +1,27 @@ +export interface HadithInfo { + [key: string]: { + hadiths: [ + { + arabicNumber: string | number; + grades: [{ name: string; grade: string }]; + hadithNumber: string | number; + reference: { book: number; hadith: number }; + }, + ]; + metadata: { + lastHadithNumber: string | number; + name: string; + sections: [ + { + name: string; + details: { + arabicNumberFirst: string | number; + arabicNumberLast: string | number; + hadithNumberFirst: string | number; + hadithNumberLast: string | number; + }; + }, + ]; + }; + }; +} diff --git a/src/types/hadith-object.ts b/src/types/hadith-object.ts new file mode 100644 index 0000000..ad27ea4 --- /dev/null +++ b/src/types/hadith-object.ts @@ -0,0 +1,18 @@ +export interface HadithObject { + metadata: { + name: string; + section: string; + sectionDetails: { + arabicNumberFirst: string | number; + arabicNumberLast: string | number; + hadithNumberFirst: string | number; + hadithNumberLast: string | number; + }; + }; + hadith: { + hadithNumber: string | number; + arabicNumber: string | number; + text: string; + grades: [{ name: string; grade: string }]; + }; +} diff --git a/src/types/index.ts b/src/types/index.ts index 487e1e4..6234ca1 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -3,6 +3,10 @@ export * from './chapter'; export * from './dialect.enum'; export * from './hadith-lang.enum'; export * from './hadith.enum'; +export * from './hadith-object'; +export * from './hadith-info'; +export * from './hadith-by-section'; +export * from './hadith-edition'; export * from './hijri-date'; export * from './prayer-timings'; export * from './tafseer.enum';