@ihsandeen/aya 1.0.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/CONTRIBUTING.md +39 -0
- package/LICENSE +21 -0
- package/README.md +141 -0
- package/dist/commands/adab.js +28 -0
- package/dist/commands/adhan.js +58 -0
- package/dist/commands/anatomy.js +29 -0
- package/dist/commands/blame.js +29 -0
- package/dist/commands/commit.js +44 -0
- package/dist/commands/diff.js +54 -0
- package/dist/commands/dua.js +34 -0
- package/dist/commands/fast.js +36 -0
- package/dist/commands/friday.js +21 -0
- package/dist/commands/hero.js +69 -0
- package/dist/commands/hijri.js +42 -0
- package/dist/commands/history.js +98 -0
- package/dist/commands/init.js +54 -0
- package/dist/commands/invest.js +26 -0
- package/dist/commands/journal.js +84 -0
- package/dist/commands/journey.js +24 -0
- package/dist/commands/lens.js +58 -0
- package/dist/commands/memorize.js +117 -0
- package/dist/commands/mirror.js +47 -0
- package/dist/commands/names.js +48 -0
- package/dist/commands/nature.js +28 -0
- package/dist/commands/nazm.js +100 -0
- package/dist/commands/parable.js +332 -0
- package/dist/commands/prayers.js +63 -0
- package/dist/commands/pull.js +28 -0
- package/dist/commands/push.js +156 -0
- package/dist/commands/qibla.js +118 -0
- package/dist/commands/repo.js +34 -0
- package/dist/commands/sabr.js +32 -0
- package/dist/commands/scene.js +54 -0
- package/dist/commands/seek.js +28 -0
- package/dist/commands/shukr.js +22 -0
- package/dist/commands/sleep.js +26 -0
- package/dist/commands/sound.js +35 -0
- package/dist/commands/status.js +109 -0
- package/dist/commands/sunnah.js +24 -0
- package/dist/commands/tafsir.js +89 -0
- package/dist/commands/tasbih.js +50 -0
- package/dist/commands/wudu.js +22 -0
- package/dist/commands/zakat.js +72 -0
- package/dist/data/commands-db.js +365 -0
- package/dist/data/events.js +105 -0
- package/dist/data/gems.js +160 -0
- package/dist/data/nak.js +616 -0
- package/dist/data/tafsir.js +157 -0
- package/dist/data/vocab.js +105 -0
- package/dist/index.js +86 -0
- package/dist/server.js +140 -0
- package/dist/utils/config.js +38 -0
- package/dist/utils/logger.js +104 -0
- package/dist/utils/printer.js +36 -0
- package/docs/index.html +1048 -0
- package/docs/repo.html +952 -0
- package/package.json +55 -0
- package/public/hero.html +285 -0
- package/public/index.html +1039 -0
- package/public/repo.html +904 -0
- package/src/commands/adab.ts +24 -0
- package/src/commands/adhan.ts +55 -0
- package/src/commands/anatomy.ts +25 -0
- package/src/commands/blame.ts +31 -0
- package/src/commands/commit.ts +42 -0
- package/src/commands/diff.ts +56 -0
- package/src/commands/dua.ts +34 -0
- package/src/commands/fast.ts +35 -0
- package/src/commands/friday.ts +17 -0
- package/src/commands/hero.ts +73 -0
- package/src/commands/hijri.ts +43 -0
- package/src/commands/history.ts +103 -0
- package/src/commands/init.ts +53 -0
- package/src/commands/invest.ts +22 -0
- package/src/commands/journal.ts +97 -0
- package/src/commands/journey.ts +20 -0
- package/src/commands/lens.ts +58 -0
- package/src/commands/memorize.ts +131 -0
- package/src/commands/mirror.ts +48 -0
- package/src/commands/names.ts +46 -0
- package/src/commands/nature.ts +24 -0
- package/src/commands/nazm.ts +102 -0
- package/src/commands/parable.ts +360 -0
- package/src/commands/prayers.ts +65 -0
- package/src/commands/pull.ts +28 -0
- package/src/commands/push.ts +171 -0
- package/src/commands/qibla.ts +127 -0
- package/src/commands/repo.ts +34 -0
- package/src/commands/sabr.ts +28 -0
- package/src/commands/scene.ts +56 -0
- package/src/commands/seek.ts +24 -0
- package/src/commands/shukr.ts +19 -0
- package/src/commands/sleep.ts +23 -0
- package/src/commands/sound.ts +34 -0
- package/src/commands/status.ts +132 -0
- package/src/commands/sunnah.ts +21 -0
- package/src/commands/tafsir.ts +86 -0
- package/src/commands/tasbih.ts +49 -0
- package/src/commands/wudu.ts +19 -0
- package/src/commands/zakat.ts +73 -0
- package/src/data/commands-db.ts +372 -0
- package/src/data/events.ts +113 -0
- package/src/data/gems.ts +163 -0
- package/src/data/nak.ts +805 -0
- package/src/data/tafsir.ts +165 -0
- package/src/data/vocab.ts +114 -0
- package/src/index.ts +94 -0
- package/src/server.ts +128 -0
- package/src/utils/config.ts +44 -0
- package/src/utils/logger.ts +122 -0
- package/src/utils/printer.ts +38 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
export interface Tafsir {
|
|
2
|
+
surah: string;
|
|
3
|
+
ayah: number;
|
|
4
|
+
steps: {
|
|
5
|
+
word: string;
|
|
6
|
+
meaning: string;
|
|
7
|
+
explanation: string;
|
|
8
|
+
}[];
|
|
9
|
+
finalThought: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const tafsirData: Tafsir[] = [
|
|
13
|
+
{
|
|
14
|
+
surah: 'Ad-Duhaa',
|
|
15
|
+
ayah: 3,
|
|
16
|
+
steps: [
|
|
17
|
+
{
|
|
18
|
+
word: 'Maa',
|
|
19
|
+
meaning: 'Not / Negation',
|
|
20
|
+
explanation: 'The sentence starts with a strong negation. Allah is immediately shutting down the whispers of the disbelievers who said He had abandoned the Prophet (saw).'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
word: 'wadda\'aka',
|
|
24
|
+
meaning: 'He said goodbye / He bid farewell',
|
|
25
|
+
explanation: 'From "wada\'a". This isn\'t just "left". It\'s a warm, affectionate goodbye. Like when a mother says goodbye to her child. Allah is saying "I didn\'t even say a warm goodbye to you, let alone abandon you."'
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
word: 'Rabbuka',
|
|
29
|
+
meaning: 'Your Lord / Your Master / Your Sustainer',
|
|
30
|
+
explanation: 'He didn\'t say "Allah". He said "Your Lord". The one who has been raising you, sustaining you, and caring for you from the beginning. It\'s personal. "YOUR" Lord.'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
word: 'wa maa qalaa',
|
|
34
|
+
meaning: 'And He is not displeased / He does not hate',
|
|
35
|
+
explanation: '"Qalaa" means intense displeasure or hate. Notice He didn\'t say "wa maa qalaa-ka" (He is not displeased with YOU). He left out the "you" (ka). Why? Because He loves the Prophet (saw) so much, He didn\'t even want to put the word "hate" and "you" in the same sentence. SubhanAllah.'
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
finalThought: "If you feel distant from Allah, know that He hasn't said goodbye. He is your Rabb. He is sustaining you even in your silence."
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
surah: 'Al-Fatiha',
|
|
42
|
+
ayah: 5,
|
|
43
|
+
steps: [
|
|
44
|
+
{
|
|
45
|
+
word: 'Iyyaka',
|
|
46
|
+
meaning: 'Only You',
|
|
47
|
+
explanation: 'Grammatically, "Na\'budu" (We worship) should come first. But Allah placed "Iyyaka" (Only You) at the front. This is "Taqdeem" for "Ikhtisas" (Exclusivity). Not "We worship You", but "It is ONLY You we worship".'
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
word: 'Na\'budu',
|
|
51
|
+
meaning: 'We worship / We enslave ourselves',
|
|
52
|
+
explanation: 'From "Abd" (Slave). Worship isn\'t just prayer. It is slavery. It is total submission. And notice "We". Even when you pray alone, you are part of the "We"—the Ummah.'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
word: 'Wa Iyyaka',
|
|
56
|
+
meaning: 'And Only You',
|
|
57
|
+
explanation: 'Repetition for emphasis. We are not just monotheists in worship, but monotheists in seeking help.'
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
word: 'Nasta\'een',
|
|
61
|
+
meaning: 'We seek help / We ask for aid',
|
|
62
|
+
explanation: 'From "Isti\'anah". This isn\'t just "help me lift this box". It is asking for help in a matter you are already struggling with. You have to make the effort first, then ask for His aid to complete it.'
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
finalThought: "You can't skip to 'Nasta'een' (Help me) without first committing to 'Na'budu' (I am your slave). The help comes to the one who serves."
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
surah: 'Al-Asr',
|
|
69
|
+
ayah: 1,
|
|
70
|
+
steps: [
|
|
71
|
+
{
|
|
72
|
+
word: 'Wal-Asr',
|
|
73
|
+
meaning: 'By Time',
|
|
74
|
+
explanation: 'Allah swears by "Time" (Asr). But Asr isn\'t just time; it\'s the squeezing of time. It\'s the late afternoon when the day is slipping away. He is swearing by the very thing we are losing every second.'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
word: 'Inna',
|
|
78
|
+
meaning: 'Indeed / Verily',
|
|
79
|
+
explanation: 'Emphasis. No doubt about it.'
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
word: 'Al-Insaan',
|
|
83
|
+
meaning: 'The Human Being',
|
|
84
|
+
explanation: 'He didn\'t say "The Disbeliever". He said "The Human". Every single one of us. We are all in the same boat.'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
word: 'La-fee Khusr',
|
|
88
|
+
meaning: 'Is surely in loss',
|
|
89
|
+
explanation: 'We aren\'t "going" to be in loss. We are *drowning* in loss right now. Like ice melting. Every breath is a capital loss unless invested.'
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
finalThought: "You are running out of time. The only way to stop the loss is to invest your time in Iman and good deeds."
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
surah: 'Al-Ikhlas',
|
|
96
|
+
ayah: 1,
|
|
97
|
+
steps: [
|
|
98
|
+
{
|
|
99
|
+
word: 'Qul',
|
|
100
|
+
meaning: 'Say / Declare',
|
|
101
|
+
explanation: 'A direct command. Don\'t just know it, announce it. This is your identity.'
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
word: 'Huwa Allahu',
|
|
105
|
+
meaning: 'He is Allah',
|
|
106
|
+
explanation: 'The name Allah is unique. It has no plural, no gender. It is the proper name of God.'
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
word: 'Ahad',
|
|
110
|
+
meaning: 'The One / The Unique',
|
|
111
|
+
explanation: 'Not "Wahid" (one in number), but "Ahad" (Unique in every way). There is nothing comparable to Him. He is a category of One.'
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
finalThought: "Purify your concept of God. He is not like anything you can imagine."
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
surah: 'Al-Falaq',
|
|
118
|
+
ayah: 1,
|
|
119
|
+
steps: [
|
|
120
|
+
{
|
|
121
|
+
word: 'Qul',
|
|
122
|
+
meaning: 'Say',
|
|
123
|
+
explanation: 'Again, a command to seek refuge actively.'
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
word: 'A\'udhu',
|
|
127
|
+
meaning: 'I seek refuge / I take cover',
|
|
128
|
+
explanation: 'Imagine a fortress. You are running into it for safety. You are admitting you are weak and need protection.'
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
word: 'Bi Rabbil Falaq',
|
|
132
|
+
meaning: 'In the Lord of the Daybreak',
|
|
133
|
+
explanation: 'Falaq is the splitting of darkness by light. Just as He splits the night to bring the dawn, He can split your problems to bring relief.'
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
finalThought: "Darkness is temporary. The Lord of the Dawn is always ready to bring the light."
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
surah: 'An-Nas',
|
|
140
|
+
ayah: 1,
|
|
141
|
+
steps: [
|
|
142
|
+
{
|
|
143
|
+
word: 'Qul A\'udhu',
|
|
144
|
+
meaning: 'Say: I seek refuge',
|
|
145
|
+
explanation: 'We start with seeking protection again.'
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
word: 'Bi Rabbin-Nas',
|
|
149
|
+
meaning: 'In the Lord of Mankind',
|
|
150
|
+
explanation: 'He created us, sustains us, and owns us.'
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
word: 'Malikin-Nas',
|
|
154
|
+
meaning: 'The King of Mankind',
|
|
155
|
+
explanation: 'He has full authority over all people, including those who wish you harm.'
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
word: 'Ilahin-Nas',
|
|
159
|
+
meaning: 'The God of Mankind',
|
|
160
|
+
explanation: 'The only one worthy of worship and total devotion.'
|
|
161
|
+
}
|
|
162
|
+
],
|
|
163
|
+
finalThought: "He is your Lord, your King, and your God. Who can harm you when you are with Him?"
|
|
164
|
+
}
|
|
165
|
+
];
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export interface Vocab {
|
|
2
|
+
id: string;
|
|
3
|
+
ayah: string;
|
|
4
|
+
missingWord: string;
|
|
5
|
+
answer: string;
|
|
6
|
+
meaning: string;
|
|
7
|
+
category: 'fatiha' | 'names_of_allah' | 'common' | 'short_surahs';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const vocabList: Vocab[] = [
|
|
11
|
+
// Surah Al-Fatiha
|
|
12
|
+
{
|
|
13
|
+
id: 'fatiha_1',
|
|
14
|
+
ayah: '_____ iyyaka na\'budu wa iyyaka nasta\'een (1:5)',
|
|
15
|
+
missingWord: '[?]',
|
|
16
|
+
answer: 'Iyyaka',
|
|
17
|
+
meaning: 'Only You',
|
|
18
|
+
category: 'fatiha'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 'fatiha_2',
|
|
22
|
+
ayah: 'Ihdina al-sirat al-_____ (1:6)',
|
|
23
|
+
missingWord: '[?]',
|
|
24
|
+
answer: 'mustaqeem',
|
|
25
|
+
meaning: 'straight / upright',
|
|
26
|
+
category: 'fatiha'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'fatiha_3',
|
|
30
|
+
ayah: 'Maliki yawm al-_____ (1:4)',
|
|
31
|
+
missingWord: '[?]',
|
|
32
|
+
answer: 'deen',
|
|
33
|
+
meaning: 'judgment / recompense',
|
|
34
|
+
category: 'fatiha'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'fatiha_4',
|
|
38
|
+
ayah: 'Al-hamdu lillahi rabbi al-_____ (1:2)',
|
|
39
|
+
missingWord: '[?]',
|
|
40
|
+
answer: 'alameen',
|
|
41
|
+
meaning: 'worlds / universe',
|
|
42
|
+
category: 'fatiha'
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
// Names of Allah
|
|
46
|
+
{
|
|
47
|
+
id: 'names_1',
|
|
48
|
+
ayah: 'Wa huwa al-Ghafoor al-_____ (85:14)',
|
|
49
|
+
missingWord: '[?]',
|
|
50
|
+
answer: 'wadood',
|
|
51
|
+
meaning: 'The Loving / Affectionate',
|
|
52
|
+
category: 'names_of_allah'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'names_2',
|
|
56
|
+
ayah: 'Qul huwa Allahu _____ (112:1)',
|
|
57
|
+
missingWord: '[?]',
|
|
58
|
+
answer: 'ahad',
|
|
59
|
+
meaning: 'The One / Unique',
|
|
60
|
+
category: 'names_of_allah'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'names_3',
|
|
64
|
+
ayah: 'Ar-Rahman _____ (55:1)',
|
|
65
|
+
missingWord: '[?]',
|
|
66
|
+
answer: 'Ar-Raheem',
|
|
67
|
+
meaning: 'The Most Merciful',
|
|
68
|
+
category: 'names_of_allah'
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
// Common Words
|
|
72
|
+
{
|
|
73
|
+
id: 'common_1',
|
|
74
|
+
ayah: 'Inna ma\'al usri _____ (94:6)',
|
|
75
|
+
missingWord: '[?]',
|
|
76
|
+
answer: 'yusra',
|
|
77
|
+
meaning: 'relief / ease',
|
|
78
|
+
category: 'common'
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'common_2',
|
|
82
|
+
ayah: 'Hasbuna Allah wa ni\'mal _____ (3:173)',
|
|
83
|
+
missingWord: '[?]',
|
|
84
|
+
answer: 'wakil',
|
|
85
|
+
meaning: 'disposer of affairs / trustee',
|
|
86
|
+
category: 'common'
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
// Short Surahs
|
|
90
|
+
{
|
|
91
|
+
id: 'short_1',
|
|
92
|
+
ayah: 'Wama _____ rabbuka wama qalaa (93:3)',
|
|
93
|
+
missingWord: '[?]',
|
|
94
|
+
answer: 'wadda\'aka',
|
|
95
|
+
meaning: 'said goodbye / abandoned',
|
|
96
|
+
category: 'short_surahs'
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 'short_2',
|
|
100
|
+
ayah: 'Inna a\'tayna kal _____ (108:1)',
|
|
101
|
+
missingWord: '[?]',
|
|
102
|
+
answer: 'kawthar',
|
|
103
|
+
meaning: 'abundance / river in paradise',
|
|
104
|
+
category: 'short_surahs'
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'short_3',
|
|
108
|
+
ayah: 'Idha ja\'a nasrullahi wal _____ (110:1)',
|
|
109
|
+
missingWord: '[?]',
|
|
110
|
+
answer: 'fath',
|
|
111
|
+
meaning: 'victory / opening',
|
|
112
|
+
category: 'short_surahs'
|
|
113
|
+
}
|
|
114
|
+
];
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import figlet from 'figlet';
|
|
5
|
+
import { initCommand } from './commands/init';
|
|
6
|
+
import { pullCommand } from './commands/pull';
|
|
7
|
+
import { statusCommand } from './commands/status';
|
|
8
|
+
import { commitCommand } from './commands/commit';
|
|
9
|
+
import { blameCommand } from './commands/blame';
|
|
10
|
+
import { pushCommand } from './commands/push';
|
|
11
|
+
import { journalCommand } from './commands/journal';
|
|
12
|
+
import { tafsirCommand } from './commands/tafsir';
|
|
13
|
+
import { memorizeCommand } from './commands/memorize';
|
|
14
|
+
import { qiblaCommand } from './commands/qibla';
|
|
15
|
+
import { adhanCommand } from './commands/adhan';
|
|
16
|
+
import { parableCommand } from './commands/parable';
|
|
17
|
+
import { historyCommand } from './commands/history';
|
|
18
|
+
import { nazmCommand } from './commands/nazm';
|
|
19
|
+
import { diffCommand } from './commands/diff';
|
|
20
|
+
import { mirrorCommand } from './commands/mirror';
|
|
21
|
+
import { soundCommand } from './commands/sound';
|
|
22
|
+
import { lensCommand } from './commands/lens';
|
|
23
|
+
import { sceneCommand } from './commands/scene';
|
|
24
|
+
import { heroCommand } from './commands/hero';
|
|
25
|
+
import { hijriCommand } from './commands/hijri';
|
|
26
|
+
import { zakatCommand } from './commands/zakat';
|
|
27
|
+
import { tasbihCommand } from './commands/tasbih';
|
|
28
|
+
import { prayersCommand } from './commands/prayers';
|
|
29
|
+
import { namesCommand } from './commands/names';
|
|
30
|
+
import { duaCommand } from './commands/dua';
|
|
31
|
+
import { fastCommand } from './commands/fast';
|
|
32
|
+
import { sunnahCommand } from './commands/sunnah';
|
|
33
|
+
import { sleepCommand } from './commands/sleep';
|
|
34
|
+
import { anatomyCommand } from './commands/anatomy';
|
|
35
|
+
import { journeyCommand } from './commands/journey';
|
|
36
|
+
import { natureCommand } from './commands/nature';
|
|
37
|
+
import { wuduCommand } from './commands/wudu';
|
|
38
|
+
import { investCommand } from './commands/invest';
|
|
39
|
+
import { sabrCommand } from './commands/sabr';
|
|
40
|
+
import { shukrCommand } from './commands/shukr';
|
|
41
|
+
import { fridayCommand } from './commands/friday';
|
|
42
|
+
import { adabCommand } from './commands/adab';
|
|
43
|
+
import { seekCommand } from './commands/seek';
|
|
44
|
+
import { repoCommand } from './commands/repo';
|
|
45
|
+
|
|
46
|
+
const program = new Command();
|
|
47
|
+
|
|
48
|
+
// Bismillah Header
|
|
49
|
+
console.log(chalk.dim('In the name of Allah, the Most Gracious, the Most Merciful'));
|
|
50
|
+
|
|
51
|
+
console.log(
|
|
52
|
+
chalk.green(
|
|
53
|
+
figlet.textSync('aya', { horizontalLayout: 'full' })
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
program
|
|
58
|
+
.name('aya')
|
|
59
|
+
.description('A CLI for the mindful Muslim developer')
|
|
60
|
+
.version('1.0.0')
|
|
61
|
+
.action(() => {
|
|
62
|
+
program.outputHelp();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Register Commands
|
|
66
|
+
const commands = [
|
|
67
|
+
initCommand, pullCommand, statusCommand, commitCommand, blameCommand,
|
|
68
|
+
pushCommand, journalCommand, tafsirCommand, memorizeCommand, qiblaCommand,
|
|
69
|
+
adhanCommand, parableCommand, historyCommand, nazmCommand, diffCommand,
|
|
70
|
+
mirrorCommand, soundCommand, lensCommand, sceneCommand, heroCommand,
|
|
71
|
+
hijriCommand, zakatCommand, tasbihCommand, prayersCommand, namesCommand,
|
|
72
|
+
duaCommand, fastCommand, sunnahCommand, sleepCommand, anatomyCommand,
|
|
73
|
+
journeyCommand, natureCommand, wuduCommand, investCommand, sabrCommand,
|
|
74
|
+
shukrCommand, fridayCommand, adabCommand, seekCommand, repoCommand
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
commands.forEach(cmd => program.addCommand(cmd));
|
|
78
|
+
|
|
79
|
+
// Global Error Handler
|
|
80
|
+
process.on('uncaughtException', (error) => {
|
|
81
|
+
if (error instanceof Error && error.message.includes('EPIPE')) {
|
|
82
|
+
// Ignore EPIPE errors (broken pipe) often caused by piping output
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
console.error(chalk.red('\n❌ An unexpected error occurred (Qadar Allah).'));
|
|
86
|
+
console.error(chalk.gray(error.message));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
program.parse(process.argv);
|
|
91
|
+
|
|
92
|
+
if (!process.argv.slice(2).length) {
|
|
93
|
+
program.outputHelp();
|
|
94
|
+
}
|
package/src/server.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import http from 'http';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { logger } from './utils/logger';
|
|
6
|
+
|
|
7
|
+
const PUBLIC_DIR = path.join(__dirname, '../public');
|
|
8
|
+
|
|
9
|
+
const serveFile = (res: http.ServerResponse, filePath: string, contentType: string = 'text/html') => {
|
|
10
|
+
fs.readFile(filePath, (err, content) => {
|
|
11
|
+
if (err) {
|
|
12
|
+
if (err.code === 'ENOENT') {
|
|
13
|
+
res.writeHead(404);
|
|
14
|
+
res.end('Not Found');
|
|
15
|
+
} else {
|
|
16
|
+
res.writeHead(500);
|
|
17
|
+
res.end(`Server Error: ${err.code}`);
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
21
|
+
res.end(content, 'utf-8');
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const readBody = (req: http.IncomingMessage): Promise<any> => {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
let body = '';
|
|
29
|
+
req.on('data', chunk => { body += chunk.toString(); });
|
|
30
|
+
req.on('end', () => {
|
|
31
|
+
try {
|
|
32
|
+
resolve(body ? JSON.parse(body) : {});
|
|
33
|
+
} catch (e) {
|
|
34
|
+
reject(e);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
req.on('error', (err) => reject(err));
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const startServer = (port = 0): Promise<number> => {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const server = http.createServer(async (req, res) => {
|
|
44
|
+
// Basic Router
|
|
45
|
+
if (req.url === '/' || req.url === '/index.html') {
|
|
46
|
+
serveFile(res, path.join(PUBLIC_DIR, 'index.html'));
|
|
47
|
+
} else if (req.url === '/repo') {
|
|
48
|
+
serveFile(res, path.join(PUBLIC_DIR, 'repo.html'));
|
|
49
|
+
} else if (req.url === '/hero') {
|
|
50
|
+
serveFile(res, path.join(PUBLIC_DIR, 'hero.html'));
|
|
51
|
+
} else if (req.url === '/api/commits') {
|
|
52
|
+
// API Endpoint: Serve commits log as JSON using the Logger utility
|
|
53
|
+
try {
|
|
54
|
+
const commits = logger.getCommits();
|
|
55
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
56
|
+
res.end(JSON.stringify(commits));
|
|
57
|
+
} catch (error) {
|
|
58
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
59
|
+
res.end(JSON.stringify({ error: 'Failed to read logs' }));
|
|
60
|
+
}
|
|
61
|
+
} else if (req.url === '/api/issues') {
|
|
62
|
+
if (req.method === 'GET') {
|
|
63
|
+
const issues = logger.getIssues();
|
|
64
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
65
|
+
res.end(JSON.stringify(issues));
|
|
66
|
+
} else if (req.method === 'POST') {
|
|
67
|
+
try {
|
|
68
|
+
const body = await readBody(req);
|
|
69
|
+
if (body.title) {
|
|
70
|
+
const issue = logger.logIssue(body.title);
|
|
71
|
+
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
72
|
+
res.end(JSON.stringify(issue));
|
|
73
|
+
} else {
|
|
74
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
75
|
+
res.end(JSON.stringify({ error: 'Title required' }));
|
|
76
|
+
}
|
|
77
|
+
} catch (e) {
|
|
78
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
79
|
+
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else if (req.url === '/api/pulls') {
|
|
83
|
+
if (req.method === 'GET') {
|
|
84
|
+
const pulls = logger.getPulls();
|
|
85
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
86
|
+
res.end(JSON.stringify(pulls));
|
|
87
|
+
} else if (req.method === 'POST') {
|
|
88
|
+
try {
|
|
89
|
+
const body = await readBody(req);
|
|
90
|
+
if (body.title) {
|
|
91
|
+
const pull = logger.logPull(body.title);
|
|
92
|
+
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
93
|
+
res.end(JSON.stringify(pull));
|
|
94
|
+
} else {
|
|
95
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
96
|
+
res.end(JSON.stringify({ error: 'Title required' }));
|
|
97
|
+
}
|
|
98
|
+
} catch (e) {
|
|
99
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
100
|
+
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
// 404 for any other route
|
|
105
|
+
res.writeHead(404);
|
|
106
|
+
res.end('Not found');
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
server.listen(port, () => {
|
|
111
|
+
const address = server.address();
|
|
112
|
+
const assignedPort = typeof address === 'string' ? 0 : (address as any).port;
|
|
113
|
+
resolve(assignedPort);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Only run directly if executed as a script (not imported)
|
|
119
|
+
if (require.main === module) {
|
|
120
|
+
startServer().then(port => {
|
|
121
|
+
console.log(chalk.green.bold(`\n 🌙 aya Landing Page is running!`));
|
|
122
|
+
console.log(chalk.white(` Open your Book of Deeds:`));
|
|
123
|
+
console.log(chalk.cyan.bold(` http://localhost:${port}/repo`));
|
|
124
|
+
console.log(chalk.white(` Open the Hero Section:`));
|
|
125
|
+
console.log(chalk.cyan.bold(` http://localhost:${port}/hero`));
|
|
126
|
+
console.log(chalk.gray(`\n Press Ctrl+C to stop.`));
|
|
127
|
+
});
|
|
128
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
|
|
5
|
+
const CONFIG_DIR = path.join(process.cwd(), '.aya');
|
|
6
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
7
|
+
|
|
8
|
+
interface UserConfig {
|
|
9
|
+
name?: string;
|
|
10
|
+
intention?: string;
|
|
11
|
+
location?: {
|
|
12
|
+
city: string;
|
|
13
|
+
country: string;
|
|
14
|
+
};
|
|
15
|
+
lastPrayerCheck?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const defaultConfig: UserConfig = {
|
|
19
|
+
location: {
|
|
20
|
+
city: 'Mecca',
|
|
21
|
+
country: 'Saudi Arabia'
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const getConfig = (): UserConfig => {
|
|
26
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
27
|
+
return defaultConfig;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
31
|
+
return JSON.parse(data);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return defaultConfig;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const setConfig = (newConfig: Partial<UserConfig>) => {
|
|
38
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
39
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
40
|
+
}
|
|
41
|
+
const currentConfig = getConfig();
|
|
42
|
+
const updatedConfig = { ...currentConfig, ...newConfig };
|
|
43
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(updatedConfig, null, 2));
|
|
44
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const CONFIG_DIR = path.join(process.cwd(), '.aya');
|
|
5
|
+
const LOG_FILE = path.join(CONFIG_DIR, 'commits.log');
|
|
6
|
+
const ISSUES_FILE = path.join(CONFIG_DIR, 'issues.log');
|
|
7
|
+
const PULLS_FILE = path.join(CONFIG_DIR, 'pulls.log');
|
|
8
|
+
|
|
9
|
+
export interface Commit {
|
|
10
|
+
timestamp: string;
|
|
11
|
+
message: string;
|
|
12
|
+
hash: string;
|
|
13
|
+
path?: string; // Optional file path simulation
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface Issue {
|
|
17
|
+
id: string;
|
|
18
|
+
title: string;
|
|
19
|
+
status: 'open' | 'closed';
|
|
20
|
+
timestamp: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface Pull {
|
|
24
|
+
id: string;
|
|
25
|
+
title: string;
|
|
26
|
+
status: 'open' | 'merged' | 'closed';
|
|
27
|
+
timestamp: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const logger = {
|
|
31
|
+
ensureInit: () => {
|
|
32
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
33
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// --- Commits (Deeds) ---
|
|
38
|
+
logCommit: (message: string): Commit => {
|
|
39
|
+
logger.ensureInit();
|
|
40
|
+
|
|
41
|
+
const timestamp = new Date().toISOString();
|
|
42
|
+
// Simple format: [ISO] Message
|
|
43
|
+
const logEntry = `[${timestamp}] ${message}\n`;
|
|
44
|
+
|
|
45
|
+
fs.appendFileSync(LOG_FILE, logEntry);
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
timestamp,
|
|
49
|
+
message,
|
|
50
|
+
hash: Math.random().toString(16).substring(2, 9)
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
getCommits: (): Commit[] => {
|
|
55
|
+
if (!fs.existsSync(LOG_FILE)) return [];
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const content = fs.readFileSync(LOG_FILE, 'utf-8');
|
|
59
|
+
const lines = content.split('\n').filter(line => line.trim());
|
|
60
|
+
|
|
61
|
+
return lines.map(line => {
|
|
62
|
+
// Match [timestamp] message
|
|
63
|
+
const match = line.match(/^\[(.*?)\] (.*)$/);
|
|
64
|
+
if (match) {
|
|
65
|
+
// Generate a deterministic-looking hash from timestamp
|
|
66
|
+
const hash = Math.abs(match[1].split('').reduce((a,b)=>{a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)).toString(16).substring(0,7);
|
|
67
|
+
return {
|
|
68
|
+
timestamp: match[1],
|
|
69
|
+
message: match[2],
|
|
70
|
+
hash: hash
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}).filter((c): c is Commit => c !== null);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error('Error reading log file:', error);
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
getTotalDeeds: (): number => {
|
|
82
|
+
if (!fs.existsSync(LOG_FILE)) return 0;
|
|
83
|
+
const content = fs.readFileSync(LOG_FILE, 'utf-8');
|
|
84
|
+
return content.split('\n').filter(line => line.trim()).length;
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
// --- Issues (Istighfar/Sins) ---
|
|
88
|
+
logIssue: (title: string): Issue => {
|
|
89
|
+
logger.ensureInit();
|
|
90
|
+
const timestamp = new Date().toISOString();
|
|
91
|
+
const id = Math.floor(Math.random() * 1000).toString();
|
|
92
|
+
const entry = JSON.stringify({ id, title, status: 'open', timestamp }) + '\n';
|
|
93
|
+
fs.appendFileSync(ISSUES_FILE, entry);
|
|
94
|
+
return { id, title, status: 'open', timestamp };
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
getIssues: (): Issue[] => {
|
|
98
|
+
if (!fs.existsSync(ISSUES_FILE)) return [];
|
|
99
|
+
try {
|
|
100
|
+
const content = fs.readFileSync(ISSUES_FILE, 'utf-8');
|
|
101
|
+
return content.trim().split('\n').map(line => JSON.parse(line));
|
|
102
|
+
} catch (e) { return []; }
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// --- Pulls (Duas) ---
|
|
106
|
+
logPull: (title: string): Pull => {
|
|
107
|
+
logger.ensureInit();
|
|
108
|
+
const timestamp = new Date().toISOString();
|
|
109
|
+
const id = Math.floor(Math.random() * 1000).toString();
|
|
110
|
+
const entry = JSON.stringify({ id, title, status: 'open', timestamp }) + '\n';
|
|
111
|
+
fs.appendFileSync(PULLS_FILE, entry);
|
|
112
|
+
return { id, title, status: 'open', timestamp };
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
getPulls: (): Pull[] => {
|
|
116
|
+
if (!fs.existsSync(PULLS_FILE)) return [];
|
|
117
|
+
try {
|
|
118
|
+
const content = fs.readFileSync(PULLS_FILE, 'utf-8');
|
|
119
|
+
return content.trim().split('\n').map(line => JSON.parse(line));
|
|
120
|
+
} catch (e) { return []; }
|
|
121
|
+
}
|
|
122
|
+
};
|