Skip to content

Commit

Permalink
imp(types): add types and mappers for hadith apis
Browse files Browse the repository at this point in the history
  • Loading branch information
dev-ahmadbilal committed Aug 29, 2024
1 parent 8841e56 commit aa927aa
Show file tree
Hide file tree
Showing 10 changed files with 384 additions and 85 deletions.
10 changes: 5 additions & 5 deletions src/azkar/azkar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand All @@ -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];
}

/**
Expand All @@ -34,15 +34,15 @@ export class Azkar {
* @returns {Map<string, Zikr[]>} - Map of all azkars by category
*/
public getAll(): Map<string, Zikr[]> {
return new Map(Object.entries(this.azkars));
return new Map(Object.entries(this.azkarCollection));
}

/**
* Get a random 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);
}

Expand Down
70 changes: 70 additions & 0 deletions src/hadith/hadith-book-lang-mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { HadithLangEnum } from '../types/hadith-lang.enum';
import { HadithBook } from '../types/hadith.enum';

export const hadithBookLanguages: Record<HadithBook, HadithLangEnum[]> = {
[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],
};
114 changes: 114 additions & 0 deletions src/hadith/hadith-response-mappers.ts
Original file line number Diff line number Diff line change
@@ -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,
},
};
}
102 changes: 22 additions & 80 deletions src/hadith/hadith.ts
Original file line number Diff line number Diff line change
@@ -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, HadithLangEnum[]> = {
[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;
Expand Down Expand Up @@ -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<any> {
private async getAllEditions(prettified: boolean = true) {
const url = `${this.baseUrl}/editions${prettified ? '.json' : '.min.json'}`;
return this.fetchData(url);
}
Expand All @@ -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<any> {
public async getEdition(book: HadithBook, lang?: HadithLangEnum): Promise<HadithEdition> {
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);
}

/**
Expand All @@ -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<any> {
public async getHadith(book: HadithBook, hadithNo: number, lang?: HadithLangEnum): Promise<HadithObject> {
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);
}

/**
Expand All @@ -135,27 +75,29 @@ 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<any> {
public async getSection(book: HadithBook, sectionNo: number, lang?: HadithLangEnum): Promise<HadithBySection> {
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<any> {
public async getBooksInfo(): Promise<HadithInfo> {
const url = `${this.baseUrl}/info.json`;
return this.fetchData(url);
const resp = (await this.fetchData(url)) as HadithInfoApiResponse;
return HadithMappers.mapHadithInfoResponse(resp);
}

/**
* Utility method to fetch data from the given API URL.
* @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<any> {
private async fetchData(url: string) {
try {
const response = await fetch(url);
if (!response.ok) {
Expand Down
Loading

0 comments on commit aa927aa

Please sign in to comment.