salat 4.3.0 → 4.6.1
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 +61 -242
- package/dist/app.js +8 -11
- package/dist/commands/cities.js +11 -0
- package/dist/commands/guide.js +10 -0
- package/dist/commands/times.js +11 -0
- package/dist/components/CitiesApp.js +10 -0
- package/dist/components/HelpApp.js +6 -0
- package/dist/{ui.js → components/TimesApp.js} +3 -3
- package/dist/{utils.js → services/utils.js} +2 -2
- package/dist/{utils.test.js → services/utils.test.js} +2 -2
- package/package.json +5 -2
- package/src/app.ts +0 -25
- package/src/constants.ts +0 -13
- package/src/data/cities.json +0 -766
- package/src/data/prayers.json +0 -20
- package/src/types.ts +0 -14
- package/src/ui.tsx +0 -142
- package/src/utils.test.ts +0 -139
- package/src/utils.ts +0 -102
- package/tests/cli.e2e.test.ts +0 -46
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -9
- /package/dist/{constants.js → services/constants.js} +0 -0
- /package/dist/{types.js → services/types.js} +0 -0
package/README.md
CHANGED
|
@@ -1,275 +1,94 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 🧭 salat-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Daily Moroccan prayers time, right in your console, at the tip of your fingers. ✨
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A modern, visually rich CLI for checking prayer times in Morocco, built with **React** and **Ink**.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[](https://www.npmjs.com/package/salat)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
---
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
## 🚀 Features
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
- **Live Countdown**: "Remaining" time updates every second in real-time.
|
|
15
|
+
- **Rich UI**: Beautiful terminal interface with colors and borders.
|
|
16
|
+
- **Morocco Focused**: Supports 190+ cities across Morocco.
|
|
17
|
+
- **Smart Caching**: Local storage caching to minimize API calls.
|
|
18
|
+
- **Developer Friendly**: Built with TypeScript and Commander.js.
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
npx salat [cityName]
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Please note that if the cityName contains space of `'` you need to use quotes, example
|
|
20
|
+
## 📦 Installation
|
|
20
21
|
|
|
21
22
|
```bash
|
|
22
|
-
|
|
23
|
-
npx salat "L'msid"
|
|
23
|
+
npm install -g salat
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
##
|
|
27
|
-
|
|
28
|
-
This is an exhaustive list of the supported cities :
|
|
29
|
-
|
|
30
|
-
- Agadir
|
|
31
|
-
- Ahfir
|
|
32
|
-
- Ain Aouda
|
|
33
|
-
- Aïn Chaïr
|
|
34
|
-
- Ait El Kak
|
|
35
|
-
- Ait Ourir
|
|
36
|
-
- Akayouar
|
|
37
|
-
- Akdal Amelchil
|
|
38
|
-
- Akdez
|
|
39
|
-
- Akhefnir
|
|
40
|
-
- Akka
|
|
41
|
-
- Aknoul
|
|
42
|
-
- Akoudal Amelchil Midelt
|
|
43
|
-
- Amkala
|
|
44
|
-
- Amsmrir
|
|
45
|
-
- Araich
|
|
46
|
-
- Arbaoua
|
|
47
|
-
- Arfoud
|
|
48
|
-
- Asa
|
|
49
|
-
- Askin
|
|
50
|
-
- Asoul
|
|
51
|
-
- Assila
|
|
52
|
-
- Azemmour
|
|
53
|
-
- Azilal
|
|
54
|
-
- Azrou
|
|
55
|
-
- Bab Bared
|
|
56
|
-
- Ben Ahmed
|
|
57
|
-
- Ben Slimane
|
|
58
|
-
- Bengrir
|
|
59
|
-
- Beni Adrar
|
|
60
|
-
- Beni Ansar
|
|
61
|
-
- Beni Mellal
|
|
62
|
-
- Beni Tejit
|
|
63
|
-
- Berkane
|
|
64
|
-
- Berrchid
|
|
65
|
-
- Bir Anzaran
|
|
66
|
-
- Bir Kandour
|
|
67
|
-
- Bouanan
|
|
68
|
-
- Bouarfa
|
|
69
|
-
- Bouikra
|
|
70
|
-
- Bouizkaren
|
|
71
|
-
- Boujdour
|
|
72
|
-
- Boukrae
|
|
73
|
-
- Boulmane
|
|
74
|
-
- Boumalen Dadas
|
|
75
|
-
- Bourd
|
|
76
|
-
- Bouskoura
|
|
77
|
-
- Bouznika
|
|
78
|
-
- Casablanca
|
|
79
|
-
- Chefchaouan
|
|
80
|
-
- Chichaoua
|
|
81
|
-
- Dakhla
|
|
82
|
-
- Debdou
|
|
83
|
-
- Demnat
|
|
84
|
-
- Deryouche
|
|
85
|
-
- El Brouj
|
|
86
|
-
- El Gara
|
|
87
|
-
- El Hajeb
|
|
88
|
-
- El Jabha
|
|
89
|
-
- El Jadida
|
|
90
|
-
- El Kasba
|
|
91
|
-
- El Mahbes
|
|
92
|
-
- El Menzel
|
|
93
|
-
- Enif
|
|
94
|
-
- Erich
|
|
95
|
-
- Errachidia
|
|
96
|
-
- Essaouira
|
|
97
|
-
- Ezak
|
|
98
|
-
- Fem Lehsan
|
|
99
|
-
- Fem Zkid
|
|
100
|
-
- Ferkhana
|
|
101
|
-
- Fes
|
|
102
|
-
- Fezouane
|
|
103
|
-
- Figuig
|
|
104
|
-
- Fnideq
|
|
105
|
-
- Fquih Ben Salah
|
|
106
|
-
- Geltat Zamour
|
|
107
|
-
- Guelmim
|
|
108
|
-
- Guercif
|
|
109
|
-
- Hoceima
|
|
110
|
-
- Igherem
|
|
111
|
-
- Ikes
|
|
112
|
-
- Imelchil
|
|
113
|
-
- Imin Telat
|
|
114
|
-
- Imntanout
|
|
115
|
-
- Imouzzer Kandar
|
|
116
|
-
- Jerada
|
|
117
|
-
- Kalaat Megouna
|
|
118
|
-
- Kalaat Sraghna
|
|
119
|
-
- Kares
|
|
120
|
-
- Kariat Ba Mohammed
|
|
121
|
-
- Kasbah Tadla
|
|
122
|
-
- Katara
|
|
123
|
-
- Kelmima
|
|
124
|
-
- Kénitra
|
|
125
|
-
- Ketama
|
|
126
|
-
- Khemis Sidi Abd Jelil
|
|
127
|
-
- Khemis Zemamra
|
|
128
|
-
- Khémissat
|
|
129
|
-
- Khenifra
|
|
130
|
-
- Khouribga
|
|
131
|
-
- Ksar El Kebir
|
|
132
|
-
- Ksar El Sghir
|
|
133
|
-
- Ksar Ich
|
|
134
|
-
- L'msid
|
|
135
|
-
- Laayoune
|
|
136
|
-
- Laayoune Sidi Mellouk
|
|
137
|
-
- Lagouira
|
|
138
|
-
- Marrakech
|
|
139
|
-
- Martil
|
|
140
|
-
- Mediek
|
|
141
|
-
- Meknes
|
|
142
|
-
- Melilla
|
|
143
|
-
- Meskoura
|
|
144
|
-
- Metmata
|
|
145
|
-
- Midelt
|
|
146
|
-
- Misour
|
|
147
|
-
- Mohammedia
|
|
148
|
-
- Moulay Bouaza
|
|
149
|
-
- Moulay Bousselham
|
|
150
|
-
- Moulay Yacoub
|
|
151
|
-
- Nador
|
|
152
|
-
- Oualidia
|
|
153
|
-
- Ouazane
|
|
154
|
-
- Oued Amlil
|
|
155
|
-
- Oued Law
|
|
156
|
-
- Oued Zam
|
|
157
|
-
- Oujda
|
|
158
|
-
- Oulad Ayad
|
|
159
|
-
- Oulad Tayma
|
|
160
|
-
- Oulmes
|
|
161
|
-
- Ourzazate
|
|
162
|
-
- Ousered
|
|
163
|
-
- Rabat
|
|
164
|
-
- Ras Alma
|
|
165
|
-
- Remani
|
|
166
|
-
- Rhamna
|
|
167
|
-
- Ribate El Kheir
|
|
168
|
-
- Risani
|
|
169
|
-
- Safi
|
|
170
|
-
- Saïdia
|
|
171
|
-
- Sebta
|
|
172
|
-
- Sefrou
|
|
173
|
-
- Selouane
|
|
174
|
-
- Settat
|
|
175
|
-
- Sidi Benour
|
|
176
|
-
- Sidi Ghanem
|
|
177
|
-
- Sidi Ifni
|
|
178
|
-
- Sidi Kacém
|
|
179
|
-
- Sidi Slimane
|
|
180
|
-
- Sidi Yahya Gharb
|
|
181
|
-
- Smara
|
|
182
|
-
- Souq Arbiâ Gharb
|
|
183
|
-
- Tafntan
|
|
184
|
-
- Tafougalt
|
|
185
|
-
- Tafraouet
|
|
186
|
-
- Tahla
|
|
187
|
-
- Tahla
|
|
188
|
-
- Talouine
|
|
189
|
-
- Talsint
|
|
190
|
-
- Tamslouhet
|
|
191
|
-
- Tanger
|
|
192
|
-
- Tantan
|
|
193
|
-
- Taounat
|
|
194
|
-
- Taourirt
|
|
195
|
-
- Tarfaya
|
|
196
|
-
- Taroudant
|
|
197
|
-
- Tasltanet
|
|
198
|
-
- Tata
|
|
199
|
-
- Taza
|
|
200
|
-
- Tazarin
|
|
201
|
-
- Tefariti
|
|
202
|
-
- Temnar
|
|
203
|
-
- Tendrara
|
|
204
|
-
- Tenghir
|
|
205
|
-
- Tenjedad
|
|
206
|
-
- Tetouan
|
|
207
|
-
- Tiflet
|
|
208
|
-
- Tindit
|
|
209
|
-
- Tisa
|
|
210
|
-
- Tisenet
|
|
211
|
-
- Tizi Ousli
|
|
212
|
-
- Tiznit
|
|
213
|
-
- Toulkoult
|
|
214
|
-
- Yefrin
|
|
215
|
-
- Yousofia
|
|
216
|
-
- Zagoura
|
|
217
|
-
- Zaouiat Ahansal
|
|
218
|
-
- Zaouiat Moulay Ibrahim
|
|
219
|
-
- Zayou
|
|
220
|
-
- Zerhoune
|
|
26
|
+
## 🛠 Usage
|
|
221
27
|
|
|
222
|
-
|
|
28
|
+
Simply run `salat` to see prayer times for the default city (Marrakech), or specify a city.
|
|
223
29
|
|
|
224
30
|
```bash
|
|
225
|
-
#
|
|
31
|
+
# Get prayer times for the default city
|
|
32
|
+
salat
|
|
226
33
|
|
|
227
|
-
|
|
34
|
+
# Get prayer times for a specific city
|
|
35
|
+
salat times Rabat
|
|
228
36
|
|
|
229
|
-
# Run
|
|
37
|
+
# Run once and exit (no live timer)
|
|
38
|
+
salat -1
|
|
230
39
|
|
|
231
|
-
|
|
40
|
+
# Show a rich visual guide
|
|
41
|
+
salat guide
|
|
232
42
|
|
|
233
|
-
#
|
|
234
|
-
|
|
235
|
-
$ salat [cityName]
|
|
43
|
+
# List all available cities
|
|
44
|
+
salat cities
|
|
236
45
|
```
|
|
237
46
|
|
|
238
|
-
|
|
47
|
+
### CLI Help
|
|
239
48
|
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
```
|
|
49
|
+
```text
|
|
50
|
+
Usage: salat [options] [command]
|
|
243
51
|
|
|
244
|
-
|
|
245
|
-

|
|
246
|
-

|
|
52
|
+
Daily Moroccan prayers time, right in your console
|
|
247
53
|
|
|
248
|
-
|
|
54
|
+
Options:
|
|
55
|
+
-V, --version output the version number
|
|
56
|
+
-h, --help display help for command
|
|
57
|
+
|
|
58
|
+
Commands:
|
|
59
|
+
times [options] [city] Get prayer times for a city
|
|
60
|
+
guide Show a rich visual guide to using salat-cli
|
|
61
|
+
cities Display the list of available city names
|
|
62
|
+
help [command] display help for command
|
|
63
|
+
```
|
|
249
64
|
|
|
250
|
-
|
|
65
|
+
## 🏗 Dependencies
|
|
251
66
|
|
|
252
|
-
|
|
67
|
+
This project is built on the shoulders of giants:
|
|
253
68
|
|
|
254
|
-
|
|
69
|
+
- [**Ink**](https://github.com/vadimdemedes/ink) - React for interactive command-line apps.
|
|
70
|
+
- [**Commander.js**](https://github.com/tj/commander) - The complete solution for node.js command-line interfaces.
|
|
71
|
+
- [**date-fns**](https://date-fns.org/) - Modern JavaScript date utility library.
|
|
72
|
+
- [**node-fetch**](https://github.com/node-fetch/node-fetch) - A light-weight module that brings `window.fetch` to Node.js.
|
|
73
|
+
- [**domino**](https://github.com/fent/domino) - Server-side DOM implementation for parsing API responses.
|
|
74
|
+
- [**node-localstorage**](https://github.com/lmaccherone/node-localstorage) - LocalStorage implementation for Node.js.
|
|
255
75
|
|
|
256
|
-
|
|
76
|
+
## 🤝 Contributing
|
|
257
77
|
|
|
258
|
-
|
|
78
|
+
Contributions are welcome! Whether it's a bug fix, a new feature, or better documentation.
|
|
259
79
|
|
|
260
|
-
|
|
80
|
+
1. **Fork** the project.
|
|
81
|
+
2. **Clone** your fork: `git clone https://github.com/kafiln/salat-cli.git`
|
|
82
|
+
3. **Install** dependencies: `npm install`
|
|
83
|
+
4. **Live Development**: `npm run dev`
|
|
84
|
+
5. **Build**: `npm run build`
|
|
85
|
+
6. **Test**: `npm test`
|
|
86
|
+
7. **Submit** a Pull Request.
|
|
261
87
|
|
|
262
|
-
|
|
263
|
-
- [x] Use localstorage-like api for caching purposes
|
|
264
|
-
- [ ] Improve performance
|
|
265
|
-
- [ ] Add unit tests
|
|
266
|
-
- [x] Add a documentation site
|
|
267
|
-
- [ ] Command to set the default city
|
|
268
|
-
- [ ] Command to display the list of available cities
|
|
269
|
-
- [ ] Command to display the time table for the whole month
|
|
88
|
+
## ⭐ Show your support
|
|
270
89
|
|
|
271
|
-
|
|
90
|
+
If this project helped you, please consider giving it a **Star** on GitHub! It means a lot.
|
|
272
91
|
|
|
273
|
-
|
|
92
|
+
---
|
|
274
93
|
|
|
275
|
-
|
|
94
|
+
Built with ❤️ by [Kafil NASDAMI](https://github.com/kafiln)
|
package/dist/app.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Project's dependencies
|
|
3
|
-
import { render } from "ink";
|
|
4
|
-
import React from "react";
|
|
5
|
-
import App from "./ui.js"; // Note the .js extension for ESM imports
|
|
6
|
-
import { Command } from "commander";
|
|
7
2
|
// Project's setup
|
|
8
3
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
4
|
+
import { citiesCommand } from "#commands/cities";
|
|
5
|
+
import { guideCommand } from "#commands/guide";
|
|
6
|
+
import { timesCommand } from "#commands/times";
|
|
7
|
+
import { Command } from "commander";
|
|
9
8
|
const program = new Command();
|
|
10
9
|
program
|
|
11
10
|
.name("salat")
|
|
12
11
|
.description("Daily Moroccan prayers time, right in your console")
|
|
13
|
-
.version("4.
|
|
14
|
-
.
|
|
15
|
-
.
|
|
16
|
-
.
|
|
17
|
-
render(React.createElement(App, { cityNameArg: city, once: options.once }));
|
|
18
|
-
});
|
|
12
|
+
.version("4.6.0")
|
|
13
|
+
.addCommand(timesCommand, { isDefault: true })
|
|
14
|
+
.addCommand(guideCommand)
|
|
15
|
+
.addCommand(citiesCommand);
|
|
19
16
|
program.parse();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import CitiesApp from "#components/CitiesApp";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { render } from "ink";
|
|
4
|
+
import React from "react";
|
|
5
|
+
export const citiesCommand = new Command("cities")
|
|
6
|
+
.description("Display the list of available city names")
|
|
7
|
+
.option("-1, --once", "Run once and exit", true) // Default to true for a static list
|
|
8
|
+
.action(() => {
|
|
9
|
+
// We always run this "once" because it's just a list
|
|
10
|
+
render(React.createElement(CitiesApp));
|
|
11
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import HelpApp from "#components/HelpApp";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { render } from "ink";
|
|
4
|
+
import React from "react";
|
|
5
|
+
export const guideCommand = new Command("guide")
|
|
6
|
+
.description("Show a rich visual guide to using salat-cli")
|
|
7
|
+
.option("-1, --once", "Run once and exit", false)
|
|
8
|
+
.action(() => {
|
|
9
|
+
render(React.createElement(HelpApp));
|
|
10
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import App from "#components/TimesApp";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { render } from "ink";
|
|
4
|
+
import React from "react";
|
|
5
|
+
export const timesCommand = new Command("times")
|
|
6
|
+
.description("Get prayer times for a city")
|
|
7
|
+
.argument("[city]", "City name")
|
|
8
|
+
.option("-1, --once", "Run once and exit", false)
|
|
9
|
+
.action((city, options) => {
|
|
10
|
+
render(React.createElement(App, { cityNameArg: city, once: options.once }));
|
|
11
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import citiesData from "../data/cities.json" with { type: "json" };
|
|
4
|
+
const CitiesApp = () => {
|
|
5
|
+
const cities = citiesData;
|
|
6
|
+
// Sort cities alphabetically
|
|
7
|
+
const sortedCities = [...cities].sort((a, b) => a.name.localeCompare(b.name));
|
|
8
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "cyan", children: ["\uD83C\uDF0D Available Cities in Morocco (", cities.length, ")"] }) }), _jsx(Box, { flexDirection: "row", flexWrap: "wrap", children: sortedCities.map((city) => (_jsxs(Box, { width: 25, marginBottom: 0, children: [_jsx(Text, { color: "gray", children: "- " }), _jsx(Text, { children: city.name })] }, city.id))) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "gray", children: ["Tip: Use these names with the 'times' command, e.g., 'salat times ", sortedCities[0]?.name, "'"] }) })] }));
|
|
9
|
+
};
|
|
10
|
+
export default CitiesApp;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
const HelpApp = () => {
|
|
4
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", children: [_jsx(Box, { marginBottom: 1, justifyContent: "center", children: _jsx(Text, { bold: true, color: "cyan", children: "\u2728 SALAT CLI GUIDE \u2728" }) }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, underline: true, children: "Usage:" }), _jsx(Text, { children: " $ salat [command] [options]" })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, underline: true, children: "Commands:" }), _jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "times [city]" }) }), _jsx(Text, { children: "Show prayer times (default)" })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "guide" }) }), _jsx(Text, { children: "Show this rich help page" })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "yellow", children: "cities" }) }), _jsx(Text, { children: "Display the list of available city names" })] })] })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, underline: true, children: "Options:" }), _jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "green", children: "-1, --once" }) }), _jsx(Text, { children: "Run once and exit" })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "green", children: "-v, --version" }) }), _jsx(Text, { children: "Show version" })] }), _jsxs(Box, { children: [_jsx(Box, { width: 20, children: _jsx(Text, { color: "green", children: "-h, --help" }) }), _jsx(Text, { children: "Show standard text help" })] })] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, children: [_jsx(Text, { italic: true, color: "gray", children: "Example:" }), _jsx(Text, { color: "white", children: " $ salat Rabat --once" }), _jsx(Text, { color: "white", children: " $ salat guide" })] }), _jsx(Box, { marginTop: 1, justifyContent: "flex-end", children: _jsx(Text, { color: "gray", children: "Tip: Press Ctrl+C to exit the live timer." }) })] }));
|
|
5
|
+
};
|
|
6
|
+
export default HelpApp;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { LOCAL_STORAGE_PATH } from "#constants";
|
|
3
|
-
import { getCityId, getCityName, getData, getNextPrayer, parsePrayerTimesFromResponse, tConv24, } from "#utils";
|
|
2
|
+
import { LOCAL_STORAGE_PATH } from "#services/constants";
|
|
3
|
+
import { getCityId, getCityName, getData, getNextPrayer, parsePrayerTimesFromResponse, tConv24, } from "#services/utils";
|
|
4
4
|
import { Box, Text, useApp } from "ink";
|
|
5
5
|
import { useEffect, useState } from "react";
|
|
6
6
|
// @ts-ignore
|
|
7
7
|
import { format } from "date-fns";
|
|
8
8
|
import { LocalStorage } from "node-localstorage";
|
|
9
|
-
import citiesData from "
|
|
9
|
+
import citiesData from "../data/cities.json" with { type: "json" };
|
|
10
10
|
const cities = citiesData;
|
|
11
11
|
const localStorage = new LocalStorage(LOCAL_STORAGE_PATH);
|
|
12
12
|
const App = ({ cityNameArg, once }) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { API_URL, DEFAULT_CITY, NOT_FOUND_ERROR } from "#constants";
|
|
1
|
+
import { API_URL, DEFAULT_CITY, NOT_FOUND_ERROR } from "#services/constants";
|
|
2
2
|
import { addDays, differenceInSeconds, format, parse } from "date-fns";
|
|
3
3
|
import domino from "domino";
|
|
4
4
|
import fetch from "node-fetch";
|
|
5
|
-
import prayersData from "
|
|
5
|
+
import prayersData from "../data/prayers.json" with { type: "json" };
|
|
6
6
|
export const getCityName = (arg, cities) => {
|
|
7
7
|
if (arg == null)
|
|
8
8
|
return DEFAULT_CITY;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as constants from '#constants';
|
|
2
|
-
import { getCityId, getCityName, getNextPrayer, parsePrayerTimesFromResponse } from '#utils';
|
|
1
|
+
import * as constants from '#services/constants';
|
|
2
|
+
import { getCityId, getCityName, getNextPrayer, parsePrayerTimesFromResponse } from '#services/utils';
|
|
3
3
|
import { parseISO } from 'date-fns';
|
|
4
4
|
import { describe, expect, it, vi } from 'vitest';
|
|
5
5
|
// Mock cities data
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "salat",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.1",
|
|
4
4
|
"imports": {
|
|
5
5
|
"#*": "./dist/*.js"
|
|
6
6
|
},
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
"salat": "dist/app.js"
|
|
12
12
|
},
|
|
13
13
|
"type": "module",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
14
17
|
"dependencies": {
|
|
15
18
|
"commander": "^14.0.3",
|
|
16
19
|
"date-fns": "^4.1.0",
|
|
@@ -22,7 +25,7 @@
|
|
|
22
25
|
},
|
|
23
26
|
"scripts": {
|
|
24
27
|
"dev": "node --no-warnings --loader ts-node/esm src/app.ts",
|
|
25
|
-
"build": "tsc",
|
|
28
|
+
"build": "tsc && chmod +x dist/app.js",
|
|
26
29
|
"start": "node dist/app.js",
|
|
27
30
|
"prestart": "npm run build",
|
|
28
31
|
"prepublishOnly": "npm run build",
|
package/src/app.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Project's dependencies
|
|
4
|
-
import { render } from "ink";
|
|
5
|
-
import React from "react";
|
|
6
|
-
import App from "./ui.js"; // Note the .js extension for ESM imports
|
|
7
|
-
|
|
8
|
-
import { Command } from "commander";
|
|
9
|
-
|
|
10
|
-
// Project's setup
|
|
11
|
-
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
12
|
-
|
|
13
|
-
const program = new Command();
|
|
14
|
-
|
|
15
|
-
program
|
|
16
|
-
.name("salat")
|
|
17
|
-
.description("Daily Moroccan prayers time, right in your console")
|
|
18
|
-
.version("4.2.0")
|
|
19
|
-
.argument("[city]", "City name")
|
|
20
|
-
.option("-1, --once", "Run once and exit", false)
|
|
21
|
-
.action((city, options) => {
|
|
22
|
-
render(React.createElement(App, { cityNameArg: city, once: options.once }));
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
program.parse();
|
package/src/constants.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const API_URL = "https://www.habous.gov.ma/prieres/horaire-api.php";
|
|
2
|
-
|
|
3
|
-
export const BANNER = ``;
|
|
4
|
-
|
|
5
|
-
export const NOT_FOUND_ERROR = `
|
|
6
|
-
Your city was not found in the list
|
|
7
|
-
Using the default city
|
|
8
|
-
----------------------
|
|
9
|
-
You may need to check the spelling
|
|
10
|
-
`;
|
|
11
|
-
|
|
12
|
-
export const DEFAULT_CITY = "Marrakech";
|
|
13
|
-
export const LOCAL_STORAGE_PATH = "./storage";
|