deen-api-client 1.0.0 → 1.1.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.
package/README.md CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  A Node.js client for the Deen API, providing easy access to Islamic resources including Hadith, Quran verses, and Duas.
4
4
 
5
+ ## Getting an API Key
6
+
7
+ To use the Deen API, you'll need a valid API key. Follow these steps to get yours:
8
+
9
+ ### Step 1: Visit the API Keys Page
10
+
11
+ Go to **[https://deen.imaniro.com/api-keys](https://deen.imaniro.com/api-keys)** to access your API key dashboard.
12
+
13
+ ### Step 2: Sign In or Create an Account
14
+
15
+ - If you already have an account, sign in with your credentials
16
+ - New user? Click on "Create Account" and fill in the registration form
17
+
18
+ ### Step 3: Generate Your API Key
19
+
20
+ 1. Once logged in, navigate to the **API Keys** section
21
+ 2. Click the **"Generate New Key"** button
22
+ 3. Give your key a descriptive name (e.g., "Production App", "Development Server")
23
+ 4. Select the appropriate permissions/plan for your needs
24
+ 5. Click **"Generate New Key"** to generate your key
25
+
26
+ ### Step 4: Copy and Secure Your Key
27
+
28
+ - Store it securely (use environment variables, never commit to version control)
29
+ - Consider using a password manager or secure vault
30
+
31
+ ### 💡 Best Practices for API Key Security
32
+
33
+ ```javascript
34
+ // DON'T: Hardcode your API key
35
+ const client = new ImaniroDeenAPIClient('your_api_key_here');
36
+
37
+ // DO: Use environment variables
38
+ const client = new ImaniroDeenAPIClient(process.env.DEEN_API_KEY);
39
+ ```
40
+
5
41
  ## Installation
6
42
 
7
43
  ```bash
@@ -22,12 +58,15 @@ const client = new ImaniroDeenAPIClient('your_api_key_here');
22
58
  // Get hadiths from Sahih al-Bukhari
23
59
  async function getHadiths() {
24
60
  try {
25
- const hadiths = await client.getHadiths('Sahih al-Bukhari', 5);
61
+ const hadiths = await client.getHadiths({
62
+ book: 'Sahih al-Bukhari',
63
+ maxLimit: 1,
64
+ });
26
65
 
27
66
  hadiths.forEach((hadith) => {
28
67
  console.log(`Book: ${hadith.book}`);
29
- console.log(`Chapter: ${hadith.chapter}`);
30
- console.log(`Text: ${hadith.text}`);
68
+ console.log(`Hadith Number: ${hadith.number}`);
69
+ console.log(`Arabic Text: ${hadith.hadith}`);
31
70
  console.log(`Translation: ${hadith.translation}`);
32
71
  console.log('---');
33
72
  });
@@ -43,15 +82,14 @@ getHadiths();
43
82
 
44
83
  ## Methods
45
84
 
46
- - getHadiths(book, maxLimits, options)
47
-
48
- - getQuranVerses(surah, verse, maxLimits, options)
49
-
50
- - getDuas(category, maxLimits, options)
51
-
52
- - searchHadith(query, book, maxLimits)
53
-
54
- - getBooks()
85
+ - getHadiths({
86
+ book: 'Sahih al-Bukhari',
87
+ narrator: 'Abu Huraira (RA)',
88
+ category: 'prayer',
89
+ authenticity: 'Sahih',
90
+ language: 'English',
91
+ maxLimit: 3
92
+ })
55
93
 
56
94
  # Error Handling
57
95
 
@@ -61,8 +99,8 @@ try {
61
99
  } catch (error) {
62
100
  if (error.name === 'AuthenticationError') {
63
101
  console.log('Invalid API key');
64
- } else if (error.name === 'RateLimitError') {
65
- console.log('Rate limit exceeded');
102
+ } else if (error.name === 'InsufficientBalanceError') {
103
+ console.log('Insuffieient Balance');
66
104
  }
67
105
  }
68
106
  ```
package/dist/client.js CHANGED
@@ -2,20 +2,20 @@ const axios = require('axios');
2
2
  const {
3
3
  DeenAPIError,
4
4
  AuthenticationError,
5
+ InsufficientBalanceError,
5
6
  RateLimitError,
6
7
  NotFoundError,
7
- ServerError
8
+ ServerError,
9
+ ValidationError
8
10
  } = require('./exceptions');
9
11
  const {
10
12
  Hadith,
11
- QuranVerse,
12
- Dua,
13
13
  APIResponse
14
14
  } = require('./models');
15
15
  class ImaniroDeenAPIClient {
16
16
  constructor(apiKey, baseURL = 'https://deen-api.imaniro.com/api/v1') {
17
17
  if (!apiKey) {
18
- throw new Error('API key is required');
18
+ throw new Error('API key is required. Get one at https://deen.imaniro.com/');
19
19
  }
20
20
  this.apiKey = apiKey;
21
21
  this.baseURL = baseURL.replace(/\/$/, '');
@@ -37,21 +37,25 @@ class ImaniroDeenAPIClient {
37
37
  data
38
38
  } = error.response;
39
39
  switch (status) {
40
+ case 400:
41
+ throw new ValidationError(data?.message || 'Invalid request parameters. See documentation at https://deen.imaniro.com/', status, data?.details);
40
42
  case 401:
41
- throw new AuthenticationError(data?.message);
43
+ throw new AuthenticationError(data?.message || 'Invalid API key. Please check your API key at https://deen.imaniro.com/', status, data?.details);
44
+ case 402:
45
+ throw new InsufficientBalanceError(data?.message || 'Insufficient balance to process request. Please top up at https://deen.imaniro.com/', status, data?.details);
42
46
  case 404:
43
- throw new NotFoundError(data?.message);
47
+ throw new NotFoundError(data?.message || 'Resource not found. Visit https://deen.imaniro.com/ for documentation', status, data?.details);
44
48
  case 429:
45
- throw new RateLimitError(data?.message);
49
+ throw new RateLimitError(data?.message || 'Rate limit exceeded. Check your usage at https://deen.imaniro.com/', status, data?.details);
46
50
  case 500:
47
- throw new ServerError(data?.message);
51
+ throw new ServerError(data?.message || 'Server error occurred. Please check status at https://deen.imaniro.com/', status, data?.details);
48
52
  default:
49
- throw new DeenAPIError(data?.message || `HTTP Error: ${status}`, status);
53
+ throw new DeenAPIError(data?.message || `HTTP Error: ${status}. Visit https://deen.imaniro.com/ for assistance`, status, data?.details);
50
54
  }
51
55
  } else if (error.request) {
52
- throw new DeenAPIError('Network error: Unable to connect to API');
56
+ throw new DeenAPIError('Network error: Unable to connect to API. Please check https://deen.imaniro.com/ for API status');
53
57
  } else {
54
- throw new DeenAPIError(error.message);
58
+ throw new DeenAPIError(`${error.message}. Visit https://deen.imaniro.com/ for support`);
55
59
  }
56
60
  });
57
61
  }
@@ -63,14 +67,70 @@ class ImaniroDeenAPIClient {
63
67
  throw error;
64
68
  }
65
69
  }
66
- async getHadiths(book, maxLimits = 10, options = {}) {
67
- const params = {
68
- book,
69
- maxLimits,
70
- ...options
71
- };
70
+
71
+ /**
72
+ * Get hadiths based on specified criteria
73
+ *
74
+ * @param {Object} options - Search criteria options
75
+ * @param {string} [options.book] - Name of the hadith book (e.g., "Sahih al-Bukhari")
76
+ * @param {string} [options.hadithNumber] - Specific hadith number
77
+ * @param {string} [options.narrator] - Name of the narrator
78
+ * @param {string} [options.category] - Category or topic of the hadith (e.g., prayer, fasting)
79
+ * @param {string} [options.authenticity] - Classification of the hadith (e.g., Sahih, Daif)
80
+ * @param {string} [options.language="English"] - Language of the hadith (default: "English")
81
+ * @param {number} [options.maxLimit=1] - Maximum number of hadiths to return (default: 1, max: 500)
82
+ * @returns {Promise<Array<Hadith>>} List of Hadith objects matching the criteria
83
+ */
84
+ async getHadiths({
85
+ book,
86
+ hadithNumber,
87
+ narrator,
88
+ category,
89
+ authenticity,
90
+ language = 'English',
91
+ // Default to English
92
+ maxLimit = 1,
93
+ ...restOptions // For any additional options
94
+ } = {}) {
95
+ // Validate maxLimit
96
+ if (maxLimit > 500) {
97
+ throw new ValidationError('maxLimit cannot exceed 500. See API limits at https://deen.imaniro.com/');
98
+ }
99
+ if (maxLimit < 1) {
100
+ throw new ValidationError('maxLimit must be at least 1');
101
+ }
102
+
103
+ // Build params object - only include fields that are provided
104
+ const params = {};
105
+
106
+ // Add optional fields only if they have truthy values (not undefined, null, or empty string)
107
+ if (book) params.book = book;
108
+ if (hadithNumber) params.hadithNumber = hadithNumber;
109
+ if (narrator) params.narrator = narrator;
110
+ if (category) params.category = category;
111
+ if (authenticity) params.authenticity = authenticity;
112
+
113
+ // Always include language (with default) and maxLimit
114
+ params.language = language;
115
+ params.maxLimit = maxLimit;
116
+
117
+ // Add any additional options
118
+ Object.assign(params, restOptions);
72
119
  const response = await this._makeRequest('hadiths', params);
73
120
  return response.data.map(item => new Hadith(item));
74
121
  }
122
+
123
+ /**
124
+ * Check API status
125
+ * @returns {Promise<Object>} API status information
126
+ */
127
+ async checkStatus() {
128
+ try {
129
+ const response = await this.client.get('/status');
130
+ return response.data;
131
+ } catch (error) {
132
+ throw error;
133
+ }
134
+ }
75
135
  }
76
136
  module.exports = ImaniroDeenAPIClient;
@@ -1,36 +1,59 @@
1
1
  class DeenAPIError extends Error {
2
- constructor(message, statusCode) {
2
+ constructor(message, statusCode, details = null) {
3
+ // Ensure message includes website reference if not already present
4
+ if (!message.includes('https://deen.imaniro.com/')) {
5
+ message = `${message} | For assistance, visit https://deen.imaniro.com/`;
6
+ }
3
7
  super(message);
4
8
  this.name = 'DeenAPIError';
5
9
  this.statusCode = statusCode;
10
+ this.details = details;
6
11
  }
7
12
  }
8
13
  class AuthenticationError extends DeenAPIError {
9
- constructor(message = 'Invalid API key') {
10
- super(message, 401);
14
+ constructor(message = 'Invalid API key. Please check your API key at https://deen.imaniro.com/', statusCode = 401, details = null) {
15
+ super(message, statusCode, details);
11
16
  this.name = 'AuthenticationError';
12
17
  }
13
18
  }
19
+ class InsufficientBalanceError extends DeenAPIError {
20
+ constructor(message = 'Insufficient balance to process request. Please top up at https://deen.imaniro.com/', statusCode = 402, details = null) {
21
+ super(message, statusCode, details);
22
+ this.name = 'InsufficientBalanceError';
23
+ }
24
+ }
25
+ class ValidationError extends DeenAPIError {
26
+ constructor(message, statusCode = 400, details = null) {
27
+ // Ensure validation errors also include website reference
28
+ if (!message.includes('https://deen.imaniro.com/')) {
29
+ message = `${message} | See documentation at https://deen.imaniro.com/`;
30
+ }
31
+ super(message, statusCode, details);
32
+ this.name = 'ValidationError';
33
+ }
34
+ }
14
35
  class RateLimitError extends DeenAPIError {
15
- constructor(message = 'Rate limit exceeded') {
16
- super(message, 429);
36
+ constructor(message = 'Rate limit exceeded. Check your usage at https://deen.imaniro.com/', statusCode = 429, details = null) {
37
+ super(message, statusCode, details);
17
38
  this.name = 'RateLimitError';
18
39
  }
19
40
  }
20
41
  class NotFoundError extends DeenAPIError {
21
- constructor(message = 'Resource not found') {
22
- super(message, 404);
42
+ constructor(message = 'Resource not found. Visit https://deen.imaniro.com/ for documentation', statusCode = 404, details = null) {
43
+ super(message, statusCode, details);
23
44
  this.name = 'NotFoundError';
24
45
  }
25
46
  }
26
47
  class ServerError extends DeenAPIError {
27
- constructor(message = 'Server error occurred') {
28
- super(message, 500);
48
+ constructor(message = 'Server error occurred. Please check status at https://deen.imaniro.com/', statusCode = 500, details = null) {
49
+ super(message, statusCode, details);
29
50
  this.name = 'ServerError';
30
51
  }
31
52
  }
32
53
  module.exports = {
33
54
  DeenAPIError,
55
+ InsufficientBalanceError,
56
+ ValidationError,
34
57
  AuthenticationError,
35
58
  RateLimitError,
36
59
  NotFoundError,
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ const {
6
6
  const {
7
7
  DeenAPIError,
8
8
  AuthenticationError,
9
+ InsufficientBalanceError,
10
+ ValidationError,
9
11
  RateLimitError,
10
12
  NotFoundError,
11
13
  ServerError
@@ -16,6 +18,8 @@ module.exports = {
16
18
  APIResponse,
17
19
  DeenAPIError,
18
20
  AuthenticationError,
21
+ InsufficientBalanceError,
22
+ ValidationError,
19
23
  RateLimitError,
20
24
  NotFoundError,
21
25
  ServerError
package/dist/models.js CHANGED
@@ -3,21 +3,44 @@ class Hadith {
3
3
  this.attribution = data.attribution || '';
4
4
  this.authenticity = data.authenticity || '';
5
5
  this.category = data.category || '';
6
- this.context = data.context | '';
7
- this.book = data.book || '';
8
- this.number = data.number || '';
6
+ this.context = data.context || '';
9
7
  this.explanation = data.explanation || '';
10
8
  this.hadith = data.hadith || '';
11
9
  this.narratedBy = data.narratedBy || '';
10
+ this.book = data.book || '';
11
+ this.hadithId = data.hadithId || '';
12
+ this.number = data.number || '';
12
13
  this.translation = data.translation || '';
13
14
  }
15
+ toJSON() {
16
+ return {
17
+ attribution: this.attribution,
18
+ authenticity: this.authenticity,
19
+ category: this.category,
20
+ context: this.context,
21
+ explanation: this.explanation,
22
+ hadith: this.hadith,
23
+ narratedBy: this.narratedBy,
24
+ book: this.book,
25
+ hadithId: this.hadithId,
26
+ number: this.number,
27
+ translation: this.translation
28
+ };
29
+ }
14
30
  }
15
31
  class APIResponse {
16
32
  constructor(data) {
17
- this.success = data.success || false;
18
- this.data = data.data || [];
33
+ this.status = data.status || 'error';
19
34
  this.message = data.message || '';
20
- this.count = data.count || 0;
35
+ this.data = data.data || [];
36
+ this.timestamp = data.timestamp ? new Date(data.timestamp) : new Date();
37
+ this.code = data.code || 200;
38
+ }
39
+ isSuccess() {
40
+ return this.status === 'success';
41
+ }
42
+ isError() {
43
+ return this.status === 'error';
21
44
  }
22
45
  }
23
46
  module.exports = {
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "deen-api-client",
3
- "version": "1.0.0",
4
- "description": "Node.js client for Deen API - Islamic resources API (Hadith, Quran, Duas)",
3
+ "version": "1.1.0",
4
+ "description": "Node.js client for Deen API - Retrieve Hadith, Quran (coming soon), and Duas (coming soon) with powerful filtering",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
+ "clean": "rm -rf dist/ lib/ node_modules/",
8
9
  "build": "babel src --out-dir dist",
9
10
  "prepublishOnly": "npm run build",
10
11
  "test": "jest",
@@ -27,7 +28,7 @@
27
28
  "type": "git",
28
29
  "url": "git+https://github.com/imaniro-tech/deen-api-js-client.git"
29
30
  },
30
- "homepage": "https://github.com/imaniro-tech/deen-api-js-client",
31
+ "homepage": "https://deen.imaniro.com/documentation",
31
32
  "bugs": {
32
33
  "url": "https://github.com/imaniro-tech/deen-api-js-client/issues"
33
34
  },