@quranjs/api 1.5.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/index.d.ts +553 -2
  2. package/dist/index.js +11 -6
  3. package/dist/index.js.map +1 -0
  4. package/dist/index.mjs +6 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/package.json +25 -21
  7. package/src/sdk/utils.ts +18 -9
  8. package/src/sdk/v4/_fetcher.ts +58 -7
  9. package/src/sdk/v4/audio.ts +30 -50
  10. package/src/sdk/v4/chapters.ts +12 -15
  11. package/src/sdk/v4/juzs.ts +7 -2
  12. package/src/sdk/v4/resources.ts +27 -31
  13. package/src/sdk/v4/search.ts +14 -13
  14. package/src/sdk/v4/verses.ts +79 -58
  15. package/src/types/BaseApiOptions.ts +6 -0
  16. package/src/types/FetchFn.ts +1 -0
  17. package/src/types/index.ts +2 -0
  18. package/dist/api.cjs.development.js +0 -2723
  19. package/dist/api.cjs.development.js.map +0 -1
  20. package/dist/api.cjs.production.min.js +0 -2
  21. package/dist/api.cjs.production.min.js.map +0 -1
  22. package/dist/api.esm.js +0 -2715
  23. package/dist/api.esm.js.map +0 -1
  24. package/dist/sdk/index.d.ts +0 -183
  25. package/dist/sdk/utils.d.ts +0 -125
  26. package/dist/sdk/v4/_fetcher.d.ts +0 -3
  27. package/dist/sdk/v4/audio.d.ts +0 -52
  28. package/dist/sdk/v4/chapters.d.ts +0 -13
  29. package/dist/sdk/v4/index.d.ts +0 -173
  30. package/dist/sdk/v4/juzs.d.ts +0 -5
  31. package/dist/sdk/v4/resources.d.ts +0 -26
  32. package/dist/sdk/v4/search.d.ts +0 -22
  33. package/dist/sdk/v4/verses.d.ts +0 -64
  34. package/dist/types/ChapterId.d.ts +0 -4
  35. package/dist/types/HizbNumber.d.ts +0 -4
  36. package/dist/types/JuzNumber.d.ts +0 -4
  37. package/dist/types/PageNumber.d.ts +0 -4
  38. package/dist/types/RubNumber.d.ts +0 -4
  39. package/dist/types/VerseKey.d.ts +0 -2
  40. package/dist/types/api/ApiResponses.d.ts +0 -18
  41. package/dist/types/api/AudioData.d.ts +0 -17
  42. package/dist/types/api/AudioResponse.d.ts +0 -8
  43. package/dist/types/api/Chapter.d.ts +0 -14
  44. package/dist/types/api/ChapterInfo.d.ts +0 -8
  45. package/dist/types/api/Footnote.d.ts +0 -6
  46. package/dist/types/api/Juz.d.ts +0 -8
  47. package/dist/types/api/Pagination.d.ts +0 -7
  48. package/dist/types/api/Reciter.d.ts +0 -21
  49. package/dist/types/api/Resources.d.ts +0 -70
  50. package/dist/types/api/Segment.d.ts +0 -4
  51. package/dist/types/api/Tafsir.d.ts +0 -7
  52. package/dist/types/api/TafsirInfo.d.ts +0 -9
  53. package/dist/types/api/TranslatedName.d.ts +0 -4
  54. package/dist/types/api/Translation.d.ts +0 -17
  55. package/dist/types/api/Transliteration.d.ts +0 -4
  56. package/dist/types/api/Verse.d.ts +0 -32
  57. package/dist/types/api/Word.d.ts +0 -28
  58. package/dist/types/api/index.d.ts +0 -18
  59. package/dist/types/index.d.ts +0 -88
  60. package/dist/types/utils.d.ts +0 -5
  61. package/dist/utils/misc.d.ts +0 -1
  62. package/dist/utils/qs-stringify.d.ts +0 -21
  63. package/src/utils/qs-stringify.ts +0 -81
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ChapterId,
3
- // HizbNumber,
3
+ HizbNumber,
4
4
  JuzNumber,
5
5
  Language,
6
6
  PageNumber,
@@ -13,61 +13,59 @@ import {
13
13
  } from '../../types';
14
14
  import { decamelize } from 'humps';
15
15
  import Utils from '../utils';
16
- import { fetcher } from './_fetcher';
17
-
18
- type GetVerseOptions = Partial<{
19
- language: Language;
20
- reciter: string | number;
21
- words: boolean;
22
- translations: string[] | number[];
23
- tafsirs: string[] | number[];
24
- wordFields: Partial<Record<WordField, boolean>>;
25
- translationFields: Partial<Record<TranslationField, boolean>>;
26
- fields: Partial<Record<VerseField, boolean>>;
27
- page: number;
28
- perPage: number;
29
- }>;
16
+ import { fetcher, mergeApiOptions } from './_fetcher';
17
+ import { BaseApiOptions } from '../../types/BaseApiOptions';
18
+
19
+ type GetVerseOptions = Partial<
20
+ BaseApiOptions & {
21
+ reciter: string | number;
22
+ words: boolean;
23
+ translations: string[] | number[];
24
+ tafsirs: string[] | number[];
25
+ wordFields: Partial<Record<WordField, boolean>>;
26
+ translationFields: Partial<Record<TranslationField, boolean>>;
27
+ fields: Partial<Record<VerseField, boolean>>;
28
+ page: number;
29
+ perPage: number;
30
+ }
31
+ >;
30
32
 
31
33
  const defaultOptions: GetVerseOptions = {
32
34
  language: Language.ARABIC,
33
35
  perPage: 50,
36
+ words: false,
34
37
  };
35
38
 
36
- const getVerseOptions = (options: GetVerseOptions = {}) => {
37
- const initial = { ...defaultOptions, ...options };
38
- const result: any = { language: initial.language, perPage: initial.perPage };
39
-
40
- if (initial.page) result.page = initial.page;
41
- if (initial.words !== undefined) result.words = initial.words;
42
- if (initial.translations)
43
- result.translations = initial.translations.join(',');
44
- if (initial.tafsirs) result.tafsirs = initial.tafsirs.join(',');
45
-
46
- if (initial.fields) {
47
- const fields: string[] = [];
48
- for (const [key, value] of Object.entries(initial.fields)) {
49
- if (value) fields.push(decamelize(key));
50
- }
51
- result.fields = fields.join(',');
52
- }
39
+ const mergeVerseOptions = (options: GetVerseOptions = {}) => {
40
+ const result = mergeApiOptions(options, defaultOptions);
41
+
42
+ // @ts-expect-error - we accept an array of strings, however, the API expects a comma separated string
43
+ if (result.translations) result.translations = result.translations.join(',');
53
44
 
54
- if (initial.wordFields) {
45
+ // @ts-expect-error - we accept an array of strings, however, the API expects a comma separated string
46
+ if (result.tafsirs) result.tafsirs = result.tafsirs.join(',');
47
+
48
+ if (result.wordFields) {
55
49
  const wordFields: string[] = [];
56
- for (const [key, value] of Object.entries(initial.wordFields)) {
50
+ Object.entries(result.wordFields).forEach(([key, value]) => {
57
51
  if (value) wordFields.push(decamelize(key));
58
- }
52
+ });
59
53
  result.wordFields = wordFields.join(',');
60
54
  }
61
55
 
62
- if (initial.translationFields) {
56
+ if (result.translationFields) {
63
57
  const translationFields: string[] = [];
64
- for (const [key, value] of Object.entries(initial.translationFields)) {
58
+ Object.entries(result.translationFields).forEach(([key, value]) => {
65
59
  if (value) translationFields.push(decamelize(key));
66
- }
60
+ });
67
61
  result.translationFields = translationFields.join(',');
68
62
  }
69
63
 
70
- if (initial.reciter) result.audio = initial.reciter;
64
+ // rename `reciter` to `audio` because the API expects `audio`
65
+ if (result.reciter) {
66
+ result.audio = result.reciter;
67
+ result.reciter = undefined;
68
+ }
71
69
 
72
70
  return result;
73
71
  };
@@ -83,9 +81,13 @@ const getVerseOptions = (options: GetVerseOptions = {}) => {
83
81
  */
84
82
  const findByKey = async (key: VerseKey, options?: GetVerseOptions) => {
85
83
  if (!Utils.isValidVerseKey(key)) throw new Error('Invalid verse key');
86
- const params = getVerseOptions(options);
84
+ const params = mergeVerseOptions(options);
87
85
  const url = `/verses/by_key/${key}`;
88
- const { verse } = await fetcher<{ verse: Verse }>(url, params);
86
+ const { verse } = await fetcher<{ verse: Verse }>(
87
+ url,
88
+ params,
89
+ options?.fetchFn
90
+ );
89
91
 
90
92
  return verse;
91
93
  };
@@ -101,9 +103,13 @@ const findByKey = async (key: VerseKey, options?: GetVerseOptions) => {
101
103
  */
102
104
  const findByChapter = async (id: ChapterId, options?: GetVerseOptions) => {
103
105
  if (!Utils.isValidChapterId(id)) throw new Error('Invalid chapter id');
104
- const params = getVerseOptions(options);
106
+ const params = mergeVerseOptions(options);
105
107
  const url = `/verses/by_chapter/${id}`;
106
- const { verses } = await fetcher<{ verses: Verse[] }>(url, params);
108
+ const { verses } = await fetcher<{ verses: Verse[] }>(
109
+ url,
110
+ params,
111
+ options?.fetchFn
112
+ );
107
113
 
108
114
  return verses;
109
115
  };
@@ -120,9 +126,13 @@ const findByChapter = async (id: ChapterId, options?: GetVerseOptions) => {
120
126
  const findByPage = async (page: PageNumber, options?: GetVerseOptions) => {
121
127
  if (!Utils.isValidQuranPage(page)) throw new Error('Invalid page');
122
128
 
123
- const params = getVerseOptions(options);
129
+ const params = mergeVerseOptions(options);
124
130
  const url = `/verses/by_page/${page}`;
125
- const { verses } = await fetcher<{ verses: Verse[] }>(url, params);
131
+ const { verses } = await fetcher<{ verses: Verse[] }>(
132
+ url,
133
+ params,
134
+ options?.fetchFn
135
+ );
126
136
 
127
137
  return verses;
128
138
  };
@@ -139,14 +149,17 @@ const findByPage = async (page: PageNumber, options?: GetVerseOptions) => {
139
149
  const findByJuz = async (juz: JuzNumber, options?: GetVerseOptions) => {
140
150
  if (!Utils.isValidJuz(juz)) throw new Error('Invalid juz');
141
151
 
142
- const params = getVerseOptions(options);
152
+ const params = mergeVerseOptions(options);
143
153
  const url = `/verses/by_juz/${juz}`;
144
- const { verses } = await fetcher<{ verses: Verse[] }>(url, params);
154
+ const { verses } = await fetcher<{ verses: Verse[] }>(
155
+ url,
156
+ params,
157
+ options?.fetchFn
158
+ );
145
159
 
146
160
  return verses;
147
161
  };
148
162
 
149
- // TODO: uncomment when API is fixed
150
163
  /**
151
164
  * Get all ayahs for a Hizb.
152
165
  * @description https://quran.api-docs.io/v4/verses/by-hizb-number
@@ -156,15 +169,19 @@ const findByJuz = async (juz: JuzNumber, options?: GetVerseOptions) => {
156
169
  * quran.v4.verses.findByHizb('1')
157
170
  * quran.v4.verses.findByHizb('29')
158
171
  */
159
- // const findByHizb = async (hizb: HizbNumber, options?: GetVerseOptions) => {
160
- // if (!Utils.isValidHizb(hizb)) throw new Error('Invalid hizb');
172
+ const findByHizb = async (hizb: HizbNumber, options?: GetVerseOptions) => {
173
+ if (!Utils.isValidHizb(hizb)) throw new Error('Invalid hizb');
161
174
 
162
- // const params = getVerseOptions(options);
163
- // const url = `/verses/by_hizb/${hizb}`;
164
- // const { verses } = await fetcher<{ verses: Verse[] }>(url, params);
175
+ const params = mergeVerseOptions(options);
176
+ const url = `/verses/by_hizb/${hizb}`;
177
+ const { verses } = await fetcher<{ verses: Verse[] }>(
178
+ url,
179
+ params,
180
+ options?.fetchFn
181
+ );
165
182
 
166
- // return verses;
167
- // };
183
+ return verses;
184
+ };
168
185
 
169
186
  // TODO: uncomment when API is fixed
170
187
  /**
@@ -194,8 +211,12 @@ const findByJuz = async (juz: JuzNumber, options?: GetVerseOptions) => {
194
211
  * quran.v4.verses.findRandom()
195
212
  */
196
213
  const findRandom = async (options?: GetVerseOptions) => {
197
- const params = getVerseOptions(options);
198
- const { verse } = await fetcher<{ verse: Verse }>('/verses/random', params);
214
+ const params = mergeVerseOptions(options);
215
+ const { verse } = await fetcher<{ verse: Verse }>(
216
+ '/verses/random',
217
+ params,
218
+ options?.fetchFn
219
+ );
199
220
 
200
221
  return verse;
201
222
  };
@@ -205,7 +226,7 @@ const verses = {
205
226
  findByChapter,
206
227
  findByPage,
207
228
  findByJuz,
208
- // findByHizb,
229
+ findByHizb,
209
230
  // findByRub,
210
231
  findRandom,
211
232
  };
@@ -0,0 +1,6 @@
1
+ import { FetchFn, Language } from '.';
2
+
3
+ export interface BaseApiOptions {
4
+ language: Language;
5
+ fetchFn?: FetchFn;
6
+ }
@@ -0,0 +1 @@
1
+ export type FetchFn = (url: string) => Promise<Record<string, unknown>>;
@@ -132,3 +132,5 @@ export * from './PageNumber';
132
132
  export * from './RubNumber';
133
133
 
134
134
  export * from './api';
135
+
136
+ export * from './FetchFn';