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 +52 -14
- package/dist/client.js +77 -17
- package/dist/exceptions.js +32 -9
- package/dist/index.js +4 -0
- package/dist/models.js +29 -6
- package/package.json +4 -3
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(
|
|
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(`
|
|
30
|
-
console.log(`Text: ${hadith.
|
|
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(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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 === '
|
|
65
|
-
console.log('
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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;
|
package/dist/exceptions.js
CHANGED
|
@@ -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,
|
|
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,
|
|
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,
|
|
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,
|
|
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.
|
|
18
|
-
this.data = data.data || [];
|
|
33
|
+
this.status = data.status || 'error';
|
|
19
34
|
this.message = data.message || '';
|
|
20
|
-
this.
|
|
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.
|
|
4
|
-
"description": "Node.js client for Deen API -
|
|
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://
|
|
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
|
},
|